Compare commits
125 Commits
cleanup/de
...
ded7c64907
| Author | SHA1 | Date | |
|---|---|---|---|
| ded7c64907 | |||
|
|
b96d996947 | ||
|
|
fc0661804f | ||
|
|
31e884359e | ||
|
|
d9d585d51a | ||
|
|
86ffcc3316 | ||
|
|
ae2d3591ee | ||
|
|
a6fb572a21 | ||
|
|
7e80cc628c | ||
|
|
e09795534c | ||
|
|
3379e9e517 | ||
|
|
a2006c2370 | ||
|
|
47f7c01c73 | ||
|
|
5c6f172b6b | ||
|
|
c0f4e888d7 | ||
|
|
d082f4f90d | ||
|
|
007b541028 | ||
|
|
b872d7a0ec | ||
|
|
214409a591 | ||
|
|
2a3f21976a | ||
|
|
a3c064be55 | ||
|
|
655cbf50f3 | ||
|
|
1e707ccefa | ||
|
|
1d38ba1141 | ||
|
|
9ea317939b | ||
|
|
353fe6d6f8 | ||
|
|
98bf7ea9dd | ||
|
|
1cedcae753 | ||
|
|
90aa29d2d4 | ||
|
|
0369446681 | ||
|
|
238dce78b5 | ||
|
|
124ff3f5e3 | ||
|
|
1cf06a8b49 | ||
|
|
a8bdb7ab59 | ||
|
|
08fd69af39 | ||
|
|
560ff103ce | ||
|
|
edc724b475 | ||
|
|
ac904c849d | ||
|
|
5481b6e0a6 | ||
|
|
eba96df631 | ||
|
|
7caa325c5f | ||
|
|
e20641e101 | ||
|
|
8f81f71802 | ||
|
|
e7a4ccecf3 | ||
|
|
ec33a8b5a9 | ||
|
|
4a9aa62831 | ||
|
|
8b5eada088 | ||
|
|
eeb947d311 | ||
|
|
430d7a8cdd | ||
|
|
c94dcdd9e6 | ||
|
|
46c514f530 | ||
|
|
b29a34c76a | ||
|
|
20ba833147 | ||
|
|
1ed47c3173 | ||
|
|
ccac1f96dd | ||
|
|
c860bfebc1 | ||
|
|
d5806c3d31 | ||
|
|
bf36825fce | ||
|
|
a1780e2c4b | ||
|
|
02850eb6e3 | ||
|
|
71efd7a96f | ||
|
|
3508e47600 | ||
|
|
eef0be09b3 | ||
|
|
2df20aea38 | ||
|
|
1032c3cb57 | ||
|
|
5f26f8de27 | ||
|
|
328550b9a3 | ||
|
|
28455ecd5d | ||
|
|
54dbea659a | ||
|
|
447c1d748a | ||
|
|
4a10887e48 | ||
|
|
48015a4c95 | ||
|
|
abbfedf3f7 | ||
|
|
fa9153deb8 | ||
|
|
b287f5c2db | ||
|
|
2ebc2d441f | ||
|
|
5f2c9eb5df | ||
|
|
ce41e24434 | ||
|
|
c5d81e94e5 | ||
|
|
0500bdee2b | ||
|
|
e9a1df9123 | ||
|
|
277a06c3de | ||
|
|
c064efc812 | ||
|
|
1408074ef4 | ||
|
|
8c1f1b69ff | ||
|
|
5783507344 | ||
|
|
ae64c5225f | ||
|
|
d2f81d446b | ||
|
|
ab5b165c68 | ||
|
|
c3d4bf0e62 | ||
|
|
60f594a948 | ||
|
|
7f74d227f0 | ||
|
|
f59429c30a | ||
|
|
40276a11f9 | ||
|
|
0e846bec3f | ||
|
|
ba376fa074 | ||
|
|
d1b54dc2c5 | ||
|
|
b9c3efa24e | ||
|
|
40e613ed8d | ||
|
|
d033def947 | ||
|
|
671e110d99 | ||
|
|
b7a31b7933 | ||
|
|
1082effc17 | ||
|
|
693983dc29 | ||
|
|
6fe212796b | ||
|
|
bb1aa4aa55 | ||
|
|
7d77e0603b | ||
|
|
9f727a0fa0 | ||
|
|
997914ec27 | ||
|
|
37f01b68e8 | ||
|
|
ca695db3ba | ||
|
|
48acabac49 | ||
|
|
d7ee278b02 | ||
|
|
191a3628b5 | ||
|
|
80750b44dc | ||
|
|
25f3dcf9a5 | ||
|
|
c17e44e9f9 | ||
|
|
0b101dde3c | ||
|
|
4d20dae079 | ||
|
|
86e4fb7603 | ||
|
|
e8d081cc67 | ||
|
|
dab38c8013 | ||
|
|
c29ecac41c | ||
|
|
4187f5e7e8 | ||
|
|
2b3b2d7fd2 |
@@ -11,6 +11,7 @@
|
|||||||
"no-tabs": "off",
|
"no-tabs": "off",
|
||||||
"no-unused-vars": ["error", {"argsIgnorePattern": "^_"}],
|
"no-unused-vars": ["error", {"argsIgnorePattern": "^_"}],
|
||||||
"no-console": 0,
|
"no-console": 0,
|
||||||
|
"default-param-last": 0,
|
||||||
"template-curly-spacing": "off",
|
"template-curly-spacing": "off",
|
||||||
"max-len": 0,
|
"max-len": 0,
|
||||||
"vue/no-v-html": 0,
|
"vue/no-v-html": 0,
|
||||||
@@ -18,6 +19,7 @@
|
|||||||
"vue/multiline-html-element-content-newline": 0,
|
"vue/multiline-html-element-content-newline": 0,
|
||||||
"vue/singleline-html-element-content-newline": 0,
|
"vue/singleline-html-element-content-newline": 0,
|
||||||
"vue/multi-word-component-names": 0,
|
"vue/multi-word-component-names": 0,
|
||||||
|
"vue/no-reserved-component-names": 0,
|
||||||
"no-param-reassign": ["error", {
|
"no-param-reassign": ["error", {
|
||||||
"props": true,
|
"props": true,
|
||||||
"ignorePropertyModificationsFor": ["state", "acc"]
|
"ignorePropertyModificationsFor": ["state", "acc"]
|
||||||
|
|||||||
1
.gitignore
vendored
@@ -3,6 +3,7 @@ dist/
|
|||||||
log/
|
log/
|
||||||
media/
|
media/
|
||||||
html/
|
html/
|
||||||
|
data/
|
||||||
tmp/*
|
tmp/*
|
||||||
public/js/*
|
public/js/*
|
||||||
public/css/*
|
public/css/*
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<router-link
|
<RouterLink
|
||||||
:to="`/actor/${actor.id}/${actor.slug}`"
|
:to="`/actor/${actor.id}/${actor.slug}`"
|
||||||
|
:target="target"
|
||||||
class="actor nolink"
|
class="actor nolink"
|
||||||
>
|
>
|
||||||
<div class="avatar">
|
<div class="avatar">
|
||||||
@@ -18,7 +19,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="name">{{ actor.name }}</span>
|
<span class="name">{{ actor.name }}</span>
|
||||||
</router-link>
|
</RouterLink>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -36,6 +37,10 @@ export default {
|
|||||||
type: Object,
|
type: Object,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
target: {
|
||||||
|
type: String,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
unstashActor,
|
unstashActor,
|
||||||
|
|||||||
@@ -41,9 +41,9 @@
|
|||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<a
|
<RouterLink
|
||||||
|
:to="hasScrolled ? '' : { name: 'actor', params: { actorId: actor.id, actorSlug: actor.slug } }"
|
||||||
class="avatar-container"
|
class="avatar-container"
|
||||||
@click="goToActor"
|
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
v-if="actor.avatar"
|
v-if="actor.avatar"
|
||||||
@@ -130,7 +130,7 @@
|
|||||||
class="country"
|
class="country"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</RouterLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -138,13 +138,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import Gender from './gender.vue';
|
import Gender from './gender.vue';
|
||||||
|
|
||||||
function goToActor() {
|
|
||||||
// can't seem to control behavior with RouterLink
|
|
||||||
if (!this.hasScrolled) {
|
|
||||||
this.$router.push({ name: 'actor', params: { actorId: this.actor.id, actorSlug: this.actor.slug } });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function stashActor() {
|
async function stashActor() {
|
||||||
this.favorited = true;
|
this.favorited = true;
|
||||||
|
|
||||||
@@ -215,7 +208,6 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
stashActor,
|
stashActor,
|
||||||
unstashActor,
|
unstashActor,
|
||||||
goToActor,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -3,13 +3,28 @@
|
|||||||
title="Add alert"
|
title="Add alert"
|
||||||
@close="$emit('close')"
|
@close="$emit('close')"
|
||||||
>
|
>
|
||||||
|
<div
|
||||||
|
v-if="error"
|
||||||
|
class="dialog-error"
|
||||||
|
>{{ error }}</div>
|
||||||
|
|
||||||
<form
|
<form
|
||||||
class="dialog-body"
|
class="dialog-body"
|
||||||
@submit.prevent="addAlert"
|
@submit.prevent="addAlert"
|
||||||
>
|
>
|
||||||
<div class="dialog-section">
|
<div class="dialog-section">
|
||||||
<h3 class="dialog-heading">
|
<h3 class="dialog-heading">
|
||||||
When<span class="dialog-description">All to appear in the same scene</span>
|
When
|
||||||
|
|
||||||
|
<label class="dialog-description noselect">
|
||||||
|
<template v-if="all">Scene must match <strong>all</strong> fields</template>
|
||||||
|
<template v-else>Scene must match <strong>any</strong> field</template>
|
||||||
|
|
||||||
|
<Toggle
|
||||||
|
:checked="all"
|
||||||
|
@change="(checked) => all = checked"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div class="alert-section">
|
<div class="alert-section">
|
||||||
@@ -29,7 +44,10 @@
|
|||||||
:key="`actor-${actor.id}`"
|
:key="`actor-${actor.id}`"
|
||||||
class="actor"
|
class="actor"
|
||||||
>
|
>
|
||||||
<ActorPreview :actor="actor" />
|
<ActorPreview
|
||||||
|
:actor="actor"
|
||||||
|
target="_blank"
|
||||||
|
/>
|
||||||
|
|
||||||
<Icon
|
<Icon
|
||||||
icon="cross3"
|
icon="cross3"
|
||||||
@@ -104,10 +122,15 @@
|
|||||||
|
|
||||||
<div class="entities">
|
<div class="entities">
|
||||||
<div
|
<div
|
||||||
v-if="entity"
|
v-for="(entity, index) in entities"
|
||||||
|
:key="`entity-${entity.id}`"
|
||||||
|
:class="{ invalid: all && index > 0 }"
|
||||||
class="entity"
|
class="entity"
|
||||||
>
|
>
|
||||||
<Entity :entity="entity" />
|
<Entity
|
||||||
|
:entity="entity"
|
||||||
|
target="_blank"
|
||||||
|
/>
|
||||||
|
|
||||||
<Icon
|
<Icon
|
||||||
icon="cross3"
|
icon="cross3"
|
||||||
@@ -116,7 +139,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Tooltip v-if="!entity">
|
<Tooltip v-if="entities.length < 1 || !all">
|
||||||
<div class="entity placeholder">
|
<div class="entity placeholder">
|
||||||
Any channel
|
Any channel
|
||||||
|
|
||||||
@@ -136,6 +159,72 @@
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="alert-section">
|
||||||
|
<h4 class="alert-heading">Matching</h4>
|
||||||
|
|
||||||
|
<ul class="matches nolist">
|
||||||
|
<li
|
||||||
|
v-for="(match, index) in matches"
|
||||||
|
:key="`match-${index}`"
|
||||||
|
class="match"
|
||||||
|
>
|
||||||
|
<span class="match-property">{{ match.property }}: </span>
|
||||||
|
|
||||||
|
<span
|
||||||
|
v-if="match.expression.slice(0, 1) === '/' && match.expression.slice(-1) === '/'"
|
||||||
|
class="match-expression"
|
||||||
|
><span class="match-slash">/</span>{{ match.expression.slice(1, -1) }}<span class="match-slash">/</span></span>
|
||||||
|
|
||||||
|
<span
|
||||||
|
v-else
|
||||||
|
class="match-expression"
|
||||||
|
>{{ match.expression }}</span>
|
||||||
|
|
||||||
|
<Icon
|
||||||
|
icon="cross3"
|
||||||
|
class="remove"
|
||||||
|
@click.native="removeMatch(index)"
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<Tooltip
|
||||||
|
v-if="!entity"
|
||||||
|
@open="$refs.expression?.focus()"
|
||||||
|
>
|
||||||
|
<li class="match placeholder">
|
||||||
|
Anything
|
||||||
|
|
||||||
|
<Icon
|
||||||
|
icon="plus3"
|
||||||
|
class="add"
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<template #tooltip>
|
||||||
|
<form
|
||||||
|
class="pattern-tooltip"
|
||||||
|
@submit.prevent="addMatch"
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
v-model="matchProperty"
|
||||||
|
class="input"
|
||||||
|
>
|
||||||
|
<option value="title">Title</option>
|
||||||
|
<option value="description">Description</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<input
|
||||||
|
ref="expression"
|
||||||
|
v-model="matchExpression"
|
||||||
|
class="input"
|
||||||
|
placeholder="Expression, // for RegExp"
|
||||||
|
>
|
||||||
|
</form>
|
||||||
|
</template>
|
||||||
|
</Tooltip>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="dialog-section">
|
<div class="dialog-section">
|
||||||
@@ -194,7 +283,7 @@
|
|||||||
|
|
||||||
<div class="dialog-actions right">
|
<div class="dialog-actions right">
|
||||||
<button
|
<button
|
||||||
:disabled="actors.length === 0 && tags.length === 0 && !entity"
|
:disabled="actors.length === 0 && tags.length === 0 && !entity && matches.length === 0"
|
||||||
type="submit"
|
type="submit"
|
||||||
class="button button-primary"
|
class="button button-primary"
|
||||||
>Add alert</button>
|
>Add alert</button>
|
||||||
@@ -207,19 +296,28 @@
|
|||||||
import ActorPreview from '../actors/preview.vue';
|
import ActorPreview from '../actors/preview.vue';
|
||||||
import Entity from '../entities/tile.vue';
|
import Entity from '../entities/tile.vue';
|
||||||
import Checkbox from '../form/checkbox.vue';
|
import Checkbox from '../form/checkbox.vue';
|
||||||
|
import Toggle from '../form/toggle.vue';
|
||||||
import Search from './search.vue';
|
import Search from './search.vue';
|
||||||
|
|
||||||
async function addAlert() {
|
async function addAlert() {
|
||||||
await this.$store.dispatch('addAlert', {
|
this.error = null;
|
||||||
actors: this.actors.map((actor) => actor.id),
|
|
||||||
tags: this.tags.map((tag) => tag.id),
|
|
||||||
entity: this.entity?.id,
|
|
||||||
notify: this.notify,
|
|
||||||
email: this.email,
|
|
||||||
stashes: this.stashes.map((stash) => stash.id),
|
|
||||||
});
|
|
||||||
|
|
||||||
this.$emit('close', true);
|
try {
|
||||||
|
await this.$store.dispatch('addAlert', {
|
||||||
|
all: this.all,
|
||||||
|
actors: this.actors.map((actor) => actor.id),
|
||||||
|
tags: this.tags.map((tag) => tag.id),
|
||||||
|
matches: this.matches,
|
||||||
|
entities: this.entities.map((entity) => entity.id),
|
||||||
|
notify: this.notify,
|
||||||
|
email: this.email,
|
||||||
|
stashes: this.stashes.map((stash) => stash.id),
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$emit('close', true);
|
||||||
|
} catch (error) {
|
||||||
|
this.error = error.message;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addActor(actor) {
|
function addActor(actor) {
|
||||||
@@ -231,7 +329,7 @@ function addActor(actor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function addEntity(entity) {
|
function addEntity(entity) {
|
||||||
this.entity = entity;
|
this.entities = this.entities.concat(entity);
|
||||||
this.events.emit('blur');
|
this.events.emit('blur');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,14 +345,34 @@ function removeActor(actor) {
|
|||||||
this.actors = this.actors.filter((listedActor) => listedActor.id !== actor.id);
|
this.actors = this.actors.filter((listedActor) => listedActor.id !== actor.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeEntity() {
|
function removeEntity(entity) {
|
||||||
this.entity = null;
|
this.entities = this.entities.filter((alertEntity) => alertEntity.id !== entity.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeTag(tag) {
|
function removeTag(tag) {
|
||||||
this.tags = this.tags.filter((listedTag) => listedTag.id !== tag.id);
|
this.tags = this.tags.filter((listedTag) => listedTag.id !== tag.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addMatch() {
|
||||||
|
if (!this.matchExpression) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.matches = this.matches.concat({
|
||||||
|
property: this.matchProperty,
|
||||||
|
expression: this.matchExpression,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.matchProperty = 'title';
|
||||||
|
this.matchExpression = null;
|
||||||
|
|
||||||
|
this.events.emit('blur');
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeMatch(removeIndex) {
|
||||||
|
this.matches = this.matches.filter((match, matchIndex) => matchIndex !== removeIndex);
|
||||||
|
}
|
||||||
|
|
||||||
function addStash(stash) {
|
function addStash(stash) {
|
||||||
if (!this.stashes.some((selectedStash) => selectedStash.id === stash.id)) {
|
if (!this.stashes.some((selectedStash) => selectedStash.id === stash.id)) {
|
||||||
this.stashes = this.stashes.concat(stash);
|
this.stashes = this.stashes.concat(stash);
|
||||||
@@ -273,13 +391,19 @@ export default {
|
|||||||
Checkbox,
|
Checkbox,
|
||||||
Entity,
|
Entity,
|
||||||
Search,
|
Search,
|
||||||
|
Toggle,
|
||||||
},
|
},
|
||||||
emits: ['close'],
|
emits: ['close'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
error: null,
|
||||||
actors: [],
|
actors: [],
|
||||||
tags: [],
|
tags: [],
|
||||||
entity: null,
|
all: true,
|
||||||
|
entities: [],
|
||||||
|
matches: [],
|
||||||
|
matchProperty: 'title',
|
||||||
|
matchExpression: null,
|
||||||
notify: true,
|
notify: true,
|
||||||
email: false,
|
email: false,
|
||||||
stashes: [],
|
stashes: [],
|
||||||
@@ -290,10 +414,12 @@ export default {
|
|||||||
addActor,
|
addActor,
|
||||||
addAlert,
|
addAlert,
|
||||||
addEntity,
|
addEntity,
|
||||||
|
addMatch,
|
||||||
addTag,
|
addTag,
|
||||||
addStash,
|
addStash,
|
||||||
removeActor,
|
removeActor,
|
||||||
removeEntity,
|
removeEntity,
|
||||||
|
removeMatch,
|
||||||
removeTag,
|
removeTag,
|
||||||
removeStash,
|
removeStash,
|
||||||
},
|
},
|
||||||
@@ -320,9 +446,24 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.dialog-description {
|
.dialog-description {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
color: var(--shadow);
|
color: var(--shadow);
|
||||||
font-size: .9rem;
|
font-size: .9rem;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
|
|
||||||
|
.toggle-container {
|
||||||
|
margin-left: .5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-error {
|
||||||
|
padding: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
background: var(--error);
|
||||||
|
color: var(--text-light);
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.alert-heading {
|
.alert-heading {
|
||||||
@@ -338,6 +479,34 @@ export default {
|
|||||||
font-size: 0;
|
font-size: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.match {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: .25rem 0;
|
||||||
|
font-family: inherit;
|
||||||
|
|
||||||
|
.remove {
|
||||||
|
position: relative;
|
||||||
|
top: -.1rem;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.match-property {
|
||||||
|
text-transform: capitalize;
|
||||||
|
color: var(--shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.match-expression {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.match-slash {
|
||||||
|
padding: 0 .1rem;
|
||||||
|
color: var(--primary);
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
.actors > .actor,
|
.actors > .actor,
|
||||||
.entity,
|
.entity,
|
||||||
.tag,
|
.tag,
|
||||||
@@ -347,6 +516,11 @@ export default {
|
|||||||
margin: 0 .5rem .5rem 0;
|
margin: 0 .5rem .5rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.entity.invalid {
|
||||||
|
opacity: .5;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
.entity .tile {
|
.entity .tile {
|
||||||
width: 10rem;
|
width: 10rem;
|
||||||
height: 2.5rem;
|
height: 2.5rem;
|
||||||
@@ -366,6 +540,14 @@ export default {
|
|||||||
color: var(--text);
|
color: var(--text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pattern-tooltip {
|
||||||
|
display: flex;
|
||||||
|
gap: .5rem;
|
||||||
|
position: relative;
|
||||||
|
padding: .5rem;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.remove {
|
.remove {
|
||||||
width: 1rem;
|
width: 1rem;
|
||||||
height: 1rem;
|
height: 1rem;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<iframe
|
<iframe
|
||||||
v-if="campaign?.banner?.type === 'html'"
|
v-if="campaign?.banner?.type === 'html'"
|
||||||
|
ref="iframe"
|
||||||
:width="campaign.banner.width"
|
:width="campaign.banner.width"
|
||||||
:height="campaign.banner.height"
|
:height="campaign.banner.height"
|
||||||
:src="getSource(campaign)"
|
:src="getSource(campaign)"
|
||||||
@@ -8,6 +9,8 @@
|
|||||||
marginwidth="0"
|
marginwidth="0"
|
||||||
marginheight="0"
|
marginheight="0"
|
||||||
class="campaign frame"
|
class="campaign frame"
|
||||||
|
data-umami-event="campaign-click"
|
||||||
|
:data-umami-event-campaign-id="`${campaign.entity.slug}-${campaign.id}`"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
@@ -15,6 +18,8 @@
|
|||||||
:href="campaign.url || campaign.affiliate?.url"
|
:href="campaign.url || campaign.affiliate?.url"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="campaign"
|
class="campaign"
|
||||||
|
data-umami-event="campaign-click"
|
||||||
|
:data-umami-event-campaign-id="`${campaign.entity.slug}-${campaign.id}`"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
:src="getSource(campaign)"
|
:src="getSource(campaign)"
|
||||||
@@ -41,7 +46,6 @@ function ratioFilter(banner) {
|
|||||||
|
|
||||||
if (banner.type === 'html' && banner.width > window.innerWidth) {
|
if (banner.type === 'html' && banner.width > window.innerWidth) {
|
||||||
// usually non-scalable iframes
|
// usually non-scalable iframes
|
||||||
console.log('TOO WIDE');
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,4 +221,17 @@ export default {
|
|||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.frame-container {
|
||||||
|
position: relative;
|
||||||
|
font-size: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.frame-target {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -96,17 +96,29 @@ function scrollToTop() {
|
|||||||
this.$refs.content.scrollTop = 0;
|
this.$refs.content.scrollTop = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function trackIframeCampaign() {
|
||||||
|
// no way to capture clicks from an iframe directly
|
||||||
|
if (window.umami && document.activeElement.tagName === 'IFRAME' && document.activeElement.dataset.umamiEvent === 'campaign-click') {
|
||||||
|
window.umami.track('campaign-click', {
|
||||||
|
'campaign-id': document.activeElement.dataset.umamiEventCampaignId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function mounted() {
|
function mounted() {
|
||||||
document.addEventListener('click', this.blur);
|
document.addEventListener('click', this.blur);
|
||||||
window.addEventListener('resize', this.resize);
|
window.addEventListener('resize', this.resize);
|
||||||
|
|
||||||
this.events.on('toggleSettings', this.toggleSettings);
|
this.events.on('toggleSettings', this.toggleSettings);
|
||||||
this.events.on('toggleSidebar', this.toggleSidebar);
|
this.events.on('toggleSidebar', this.toggleSidebar);
|
||||||
|
|
||||||
|
window.addEventListener('blur', this.trackIframeCampaign);
|
||||||
}
|
}
|
||||||
|
|
||||||
function beforeUnmount() {
|
function beforeUnmount() {
|
||||||
document.removeEventListener('click', this.blur);
|
document.removeEventListener('click', this.blur);
|
||||||
window.removeEventListener('resize', this.resize);
|
window.removeEventListener('resize', this.resize);
|
||||||
|
window.removeEventListener('blur', this.trackIframeCampaign);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -129,10 +141,11 @@ export default {
|
|||||||
mounted,
|
mounted,
|
||||||
beforeUnmount,
|
beforeUnmount,
|
||||||
methods: {
|
methods: {
|
||||||
|
setConsent,
|
||||||
toggleSidebar,
|
toggleSidebar,
|
||||||
toggleFilters,
|
toggleFilters,
|
||||||
toggleSettings,
|
toggleSettings,
|
||||||
setConsent,
|
trackIframeCampaign,
|
||||||
blur,
|
blur,
|
||||||
resize,
|
resize,
|
||||||
scroll,
|
scroll,
|
||||||
|
|||||||
@@ -20,13 +20,13 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
EntityTile,
|
EntityTile,
|
||||||
},
|
},
|
||||||
emits: ['load'],
|
|
||||||
props: {
|
props: {
|
||||||
entity: {
|
entity: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
emits: ['load'],
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<router-link
|
<RouterLink
|
||||||
:to="`/${entity.type}/${entity.slug}`"
|
:to="`/${entity.type}/${entity.slug}`"
|
||||||
:title="entity.name"
|
:title="entity.name"
|
||||||
|
:target="target"
|
||||||
class="tile"
|
class="tile"
|
||||||
>
|
>
|
||||||
<div class="tile-logo">
|
<div class="tile-logo">
|
||||||
@@ -47,7 +48,7 @@
|
|||||||
<span v-if="typeof entity.sceneTotal !== 'undefined'">{{ entity.sceneTotal }} scenes</span>
|
<span v-if="typeof entity.sceneTotal !== 'undefined'">{{ entity.sceneTotal }} scenes</span>
|
||||||
<span v-if="entity.type === 'network'">{{ entity.childrenTotal }} channels</span>
|
<span v-if="entity.type === 'network'">{{ entity.childrenTotal }} channels</span>
|
||||||
</span>
|
</span>
|
||||||
</router-link>
|
</RouterLink>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -57,6 +58,10 @@ export default {
|
|||||||
type: Object,
|
type: Object,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
target: {
|
||||||
|
type: String,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
emits: ['load'],
|
emits: ['load'],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -99,7 +99,7 @@
|
|||||||
|
|
||||||
<Icon
|
<Icon
|
||||||
v-if="notification.alert"
|
v-if="notification.alert"
|
||||||
v-tooltip="`You set an alert for <strong>${notification.alert.tags.map(tag => tag.name).join(', ') || 'all'}</strong> scenes with <strong>${notification.alert.actors.map(actor => actor.name).join(', ') || 'any actor'}</strong> for <strong>${notification.alert.entity?.name || 'any channel'}</strong>`"
|
v-tooltip="`You set an alert for scenes with <strong>${notification.alert.all ? 'all of' : 'any of'}</strong> <strong>${notification.alert.actors.map(actor => actor.name).join(', ') || 'any actor'}</strong> containing <strong>${notification.alert.tags.map(tag => tag.name).join(', ') || 'any tags'}</strong> from <strong>${notification.alert.entities.map((entity) => entity.name).join(', ') || 'any channel'}</strong> matching <strong>${notification.alert.matches.map((match) => `${match.property}: ${match.expression}`).join(', ') || 'any text'}</strong>`"
|
||||||
icon="question5"
|
icon="question5"
|
||||||
@click.prevent.stop
|
@click.prevent.stop
|
||||||
/>
|
/>
|
||||||
@@ -145,12 +145,12 @@ export default {
|
|||||||
default: 0,
|
default: 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
emits: ['addAlert'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
showAddAlert: false,
|
showAddAlert: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
emits: ['addAlert'],
|
|
||||||
methods: {
|
methods: {
|
||||||
checkNotifications,
|
checkNotifications,
|
||||||
checkNotification,
|
checkNotification,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div class="media-container">
|
<div class="media-container">
|
||||||
<div
|
<div
|
||||||
class="media"
|
class="media"
|
||||||
:class="{ center: (release.photos?.length || 0) + (release.scenesPhotos?.length || 0) < 2, preview: !me }"
|
:class="{ center: (release.photos?.length || 0) + (release.caps?.length || 0) + (release.scenesPhotos?.length || 0) < 2, preview: !me }"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-if="release.trailer || release.teaser"
|
v-if="release.trailer || release.teaser"
|
||||||
@@ -169,9 +169,10 @@ function photos() {
|
|||||||
const clips = this.release.clips || [];
|
const clips = this.release.clips || [];
|
||||||
const clipPostersById = clips.reduce((acc, clip) => ({ ...acc, [clip.poster.id]: clip.poster }), {});
|
const clipPostersById = clips.reduce((acc, clip) => ({ ...acc, [clip.poster.id]: clip.poster }), {});
|
||||||
const uniqueClipPosters = Array.from(new Set(clips.map((clip) => clip.poster.id) || [])).map((posterId) => clipPostersById[posterId]);
|
const uniqueClipPosters = Array.from(new Set(clips.map((clip) => clip.poster.id) || [])).map((posterId) => clipPostersById[posterId]);
|
||||||
const photosWithClipPosters = (this.release.photos || []).concat(this.release.scenesPhotos || []).concat(uniqueClipPosters);
|
const photosWithClipPosters = (this.release.photos || []).concat(this.release.caps || []).concat(this.release.scenesPhotos || []).concat(uniqueClipPosters);
|
||||||
|
|
||||||
if (this.release.trailer || (this.release.teaser && this.release.teaser.mime !== 'image/gif')) {
|
if (this.release.trailer || (this.release.teaser && this.release.teaser.mime !== 'image/gif')) {
|
||||||
|
// if (this.release.trailer) {
|
||||||
// poster will be on trailer video
|
// poster will be on trailer video
|
||||||
return photosWithClipPosters;
|
return photosWithClipPosters;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,21 +21,24 @@
|
|||||||
<Details :release="release" />
|
<Details :release="release" />
|
||||||
|
|
||||||
<button
|
<button
|
||||||
v-if="release.photos?.length > 0 || release.scenesPhotos?.length > 0"
|
v-if="showAlbum"
|
||||||
class="album-toggle"
|
class="album-toggle"
|
||||||
@click="$router.push({ hash: '#album' })"
|
@click="$router.push({ hash: '#album' })"
|
||||||
><Icon icon="grid3" />View album</button>
|
><Icon icon="grid3" />View album</button>
|
||||||
|
|
||||||
<Album
|
<Album
|
||||||
v-if="showAlbum"
|
v-if="showAlbum && $route.hash === '#album'"
|
||||||
:items="[release.poster, ...(release.photos || []), ...(release.scenesPhotos || [])]"
|
:items="[release.poster, ...(release.photos || []), ...(release.caps || []), ...(release.scenesPhotos || [])]"
|
||||||
:title="release.title"
|
:title="release.title"
|
||||||
:path="config.media.mediaPath"
|
:path="config.media.mediaPath"
|
||||||
@close="$router.replace({ hash: undefined })"
|
@close="$router.replace({ hash: undefined })"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="info column">
|
<div class="info column">
|
||||||
<div class="row row-title">
|
<div
|
||||||
|
class="row row-title"
|
||||||
|
:class="{ 'has-alt': release.altTitles?.length > 0 }"
|
||||||
|
>
|
||||||
<h2
|
<h2
|
||||||
v-if="release.title"
|
v-if="release.title"
|
||||||
class="title"
|
class="title"
|
||||||
@@ -62,6 +65,19 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="release.altTitles?.length > 0"
|
||||||
|
class="row alttitles"
|
||||||
|
>
|
||||||
|
<h2
|
||||||
|
v-for="(altTitle, index) in release.altTitles"
|
||||||
|
:key="`altitle-${index}`"
|
||||||
|
class="alttitle"
|
||||||
|
>
|
||||||
|
{{ altTitle }}
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Releases
|
<Releases
|
||||||
v-if="release.scenes && release.scenes.length > 0"
|
v-if="release.scenes && release.scenes.length > 0"
|
||||||
:releases="release.scenes"
|
:releases="release.scenes"
|
||||||
@@ -155,6 +171,14 @@
|
|||||||
<div class="duration">{{ formatDuration(release.duration) }}</div>
|
<div class="duration">{{ formatDuration(release.duration) }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="release.photoCount"
|
||||||
|
class="row-tidbit"
|
||||||
|
>
|
||||||
|
<span class="row-label">Photos</span>
|
||||||
|
{{ release.photoCount }}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="release.shootId"
|
v-if="release.shootId"
|
||||||
class="row-tidbit"
|
class="row-tidbit"
|
||||||
@@ -391,7 +415,7 @@ function pageTitle() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function showAlbum() {
|
function showAlbum() {
|
||||||
return (this.release.photos?.length > 0 || this.release.scenesPhotos?.length > 0) && this.$route.hash === '#album';
|
return this.release.photos?.length > 0 || this.release.caps?.length > 0 || this.release.scenesPhotos?.length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function mounted() {
|
async function mounted() {
|
||||||
@@ -520,6 +544,11 @@ export default {
|
|||||||
color: var(--shadow);
|
color: var(--shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.alttitle {
|
||||||
|
color: var(--shadow);
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
.album-toggle {
|
.album-toggle {
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
|||||||
@@ -57,7 +57,12 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import config from 'config';
|
import config from 'config';
|
||||||
|
|
||||||
import { defineProps, defineEmits, computed } from 'vue';
|
import {
|
||||||
|
defineProps,
|
||||||
|
defineEmits,
|
||||||
|
computed,
|
||||||
|
} from 'vue';
|
||||||
|
|
||||||
import { useStore } from 'vuex';
|
import { useStore } from 'vuex';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<span
|
<span
|
||||||
v-if="!loading && actors.length === 0 && releases.length === 0"
|
v-if="error"
|
||||||
|
class="error summary"
|
||||||
|
>{{ error }}</span>
|
||||||
|
|
||||||
|
<span
|
||||||
|
v-else-if="!loading && actors.length === 0 && releases.length === 0"
|
||||||
class="summary"
|
class="summary"
|
||||||
>No results</span>
|
>No results</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -39,16 +44,23 @@ import Actor from '../actors/tile.vue';
|
|||||||
import Releases from '../releases/releases.vue';
|
import Releases from '../releases/releases.vue';
|
||||||
|
|
||||||
async function search() {
|
async function search() {
|
||||||
const results = await this.$store.dispatch('search', {
|
try {
|
||||||
query: this.query,
|
const results = await this.$store.dispatch('search', {
|
||||||
limit: 10,
|
query: this.query,
|
||||||
});
|
limit: 10,
|
||||||
|
});
|
||||||
|
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
|
|
||||||
if (results) {
|
if (results) {
|
||||||
this.actors = results.actors;
|
this.actors = results.actors;
|
||||||
this.releases = results.releases;
|
this.releases = results.releases;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.loading = false;
|
||||||
|
this.error = 'Failed to retrieve search results, sorry about that.';
|
||||||
|
|
||||||
|
console.error(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,6 +113,10 @@ export default {
|
|||||||
margin: 0 0 1rem 0;
|
margin: 0 0 1rem 0;
|
||||||
color: var(--shadow);
|
color: var(--shadow);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
color: var(--error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tiles {
|
.tiles {
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ function mounted() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
emits: ['open', 'close'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
opened: false,
|
opened: false,
|
||||||
@@ -133,7 +134,6 @@ export default {
|
|||||||
arrowOffset: 0,
|
arrowOffset: 0,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
emits: ['open', 'close'],
|
|
||||||
mounted,
|
mounted,
|
||||||
methods: {
|
methods: {
|
||||||
calculate,
|
calculate,
|
||||||
|
|||||||
@@ -93,17 +93,43 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="alert.entity"
|
v-if="alert.entities.length > 0"
|
||||||
class="alert-section alert-trigger"
|
class="alert-section alert-trigger"
|
||||||
>
|
>
|
||||||
<h4 class="alert-heading">Channel</h4>
|
<h4 class="alert-heading">{{ alert.entities.length > 1 ? 'Channels' : 'Channel' }}</h4>
|
||||||
|
|
||||||
<Entity
|
<Entity
|
||||||
v-if="alert.entity"
|
v-for="entity in alert.entities"
|
||||||
:entity="alert.entity"
|
:key="`${alert.id}${entity.id}`"
|
||||||
|
:entity="entity"
|
||||||
class="entity"
|
class="entity"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="alert.matches.length > 0"
|
||||||
|
class="alert-section alert-trigger"
|
||||||
|
>
|
||||||
|
<h4 class="alert-heading">Matches</h4>
|
||||||
|
|
||||||
|
<ul class="alert-matches nolist">
|
||||||
|
<li
|
||||||
|
v-for="match in alert.matches"
|
||||||
|
:key="`match-${match.id}`"
|
||||||
|
class="match"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
v-if="match.expression.slice(0, 1) === '/' && match.expression.slice(-1) === '/'"
|
||||||
|
class="match-expression"
|
||||||
|
><span class="match-slash">/</span>{{ match.expression.slice(1, -1) }}<span class="match-slash">/</span></span>
|
||||||
|
|
||||||
|
<span
|
||||||
|
v-else
|
||||||
|
class="match-expression"
|
||||||
|
>{{ match.expression }}</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -227,26 +253,34 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.alert-actors,
|
.alert-actors,
|
||||||
.alert-tags {
|
.alert-tags,
|
||||||
|
.alert-matches {
|
||||||
display: flex;
|
display: flex;
|
||||||
grid-gap: .5rem;
|
grid-gap: .5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tag {
|
.tag,
|
||||||
|
.match {
|
||||||
color: var(--shadow-strong);
|
color: var(--shadow-strong);
|
||||||
padding: .5rem;
|
padding: .5rem;
|
||||||
border: solid 1px var(--shadow-hint);
|
border: solid 1px var(--shadow-hint);
|
||||||
font-size: .9rem;
|
font-size: .9rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
.tag:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border: solid 1px var(--primary);
|
border: solid 1px var(--primary);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.entity {
|
.entity {
|
||||||
width: 10rem;
|
width: 10rem;
|
||||||
height: 2.5rem;
|
height: 2.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.match-slash {
|
||||||
|
padding: 0 .1rem;
|
||||||
|
color: var(--primary);
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -18,6 +18,10 @@
|
|||||||
<link rel="stylesheet" href="/css/style.css">
|
<link rel="stylesheet" href="/css/style.css">
|
||||||
|
|
||||||
<script src="/js/bundle.js" defer></script>
|
<script src="/js/bundle.js" defer></script>
|
||||||
|
|
||||||
|
<% if (analytics.enabled) { %>
|
||||||
|
<script async src="<%- analytics.address %>" data-website-id="<%- analytics.siteId %>"></script>
|
||||||
|
<% } %>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="container"></div>
|
<div id="container"></div>
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ function curateRelease(release, type = 'scene', context = {}) {
|
|||||||
curatedRelease.series = release.series?.filter(Boolean).map(({ serie }) => curateRelease(serie, 'serie', context)) || [];
|
curatedRelease.series = release.series?.filter(Boolean).map(({ serie }) => curateRelease(serie, 'serie', context)) || [];
|
||||||
curatedRelease.chapters = release.chapters?.filter(Boolean).map((chapter) => curateRelease(chapter, 'chapter', context)) || [];
|
curatedRelease.chapters = release.chapters?.filter(Boolean).map((chapter) => curateRelease(chapter, 'chapter', context)) || [];
|
||||||
curatedRelease.photos = release.photos?.filter(Boolean).map((photo) => photo.media || photo) || [];
|
curatedRelease.photos = release.photos?.filter(Boolean).map((photo) => photo.media || photo) || [];
|
||||||
|
curatedRelease.caps = release.caps?.filter(Boolean).map((cap) => cap.media || cap) || [];
|
||||||
curatedRelease.scenesPhotos = release.scenesPhotos?.filter(Boolean).map((photo) => photo.media || photo) || [];
|
curatedRelease.scenesPhotos = release.scenesPhotos?.filter(Boolean).map((photo) => photo.media || photo) || [];
|
||||||
curatedRelease.covers = release.covers?.filter(Boolean).map(({ media }) => media) || [];
|
curatedRelease.covers = release.covers?.filter(Boolean).map(({ media }) => media) || [];
|
||||||
|
|
||||||
@@ -190,6 +191,10 @@ function curateAlert(alert) {
|
|||||||
curatedAlert.entity = curateEntity(alert.entity.entity || alert.entity);
|
curatedAlert.entity = curateEntity(alert.entity.entity || alert.entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (alert.entities) {
|
||||||
|
curatedAlert.entities = alert.entities.map((entity) => curateEntity(entity.entity || entity));
|
||||||
|
}
|
||||||
|
|
||||||
if (alert.stashes) {
|
if (alert.stashes) {
|
||||||
curatedAlert.stashes = alert.stashes.map((stash) => curateStash(stash.stash || stash));
|
curatedAlert.stashes = alert.stashes.map((stash) => curateStash(stash.stash || stash));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ function initEntitiesActions(store, router) {
|
|||||||
$offset: Int = 0,
|
$offset: Int = 0,
|
||||||
$after: Datetime = "1900-01-01",
|
$after: Datetime = "1900-01-01",
|
||||||
$before: Datetime = "2100-01-01",
|
$before: Datetime = "2100-01-01",
|
||||||
$orderBy: [ReleasesOrderBy!]
|
$orderBy: [ReleasesSummariesOrderBy!]
|
||||||
$exclude: [String!]
|
$exclude: [String!]
|
||||||
$hasAuth: Boolean!
|
$hasAuth: Boolean!
|
||||||
$userId: Int
|
$userId: Int
|
||||||
@@ -67,7 +67,6 @@ function initEntitiesActions(store, router) {
|
|||||||
independent
|
independent
|
||||||
hasLogo
|
hasLogo
|
||||||
${campaignsFragment}
|
${campaignsFragment}
|
||||||
sceneTotal
|
|
||||||
children: childEntitiesConnection {
|
children: childEntitiesConnection {
|
||||||
totalCount
|
totalCount
|
||||||
}
|
}
|
||||||
@@ -85,50 +84,47 @@ function initEntitiesActions(store, router) {
|
|||||||
${campaignsFragment}
|
${campaignsFragment}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
connection: releasesConnection(
|
connection: releasesSummariesConnection(
|
||||||
first: $limit
|
first: $limit
|
||||||
offset: $offset
|
offset: $offset
|
||||||
orderBy: $orderBy
|
orderBy: $orderBy
|
||||||
filter: {
|
filter: {
|
||||||
entity: {
|
effectiveDate: { lessThan: $before, greaterThan: $after }
|
||||||
or: [
|
showcased: { equalTo: true }
|
||||||
{
|
and: [
|
||||||
slug: { equalTo: $entitySlug }
|
{
|
||||||
type: { equalTo: $entityType }
|
or: [
|
||||||
}
|
{
|
||||||
{
|
not: { tags: { overlaps: $exclude } }
|
||||||
parent:{
|
|
||||||
slug: { equalTo: $entitySlug }
|
|
||||||
type: { equalTo: $entityType }
|
|
||||||
}
|
}
|
||||||
}
|
{
|
||||||
{
|
tags: { isNull: true }
|
||||||
parent:{
|
|
||||||
parent: {
|
|
||||||
slug: { equalTo: $entitySlug }
|
|
||||||
type: { equalTo: $entityType }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
]
|
||||||
]
|
|
||||||
}
|
|
||||||
effectiveDate: {
|
|
||||||
lessThan: $before,
|
|
||||||
greaterThan: $after
|
|
||||||
}
|
|
||||||
releasesTagsConnection: {
|
|
||||||
none: {
|
|
||||||
tag: {
|
|
||||||
slug: {
|
|
||||||
in: $exclude
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
{
|
||||||
|
or: [
|
||||||
|
{
|
||||||
|
channelSlug: { equalTo: $entitySlug }
|
||||||
|
channelType: { equalTo: $entityType }
|
||||||
|
}
|
||||||
|
{
|
||||||
|
networkSlug: { equalTo: $entitySlug }
|
||||||
|
networkType: { equalTo: $entityType }
|
||||||
|
}
|
||||||
|
{
|
||||||
|
parentNetworkSlug: { equalTo: $entitySlug }
|
||||||
|
parentNetworkType: { equalTo: $entityType }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
releases: nodes {
|
releases: nodes {
|
||||||
${releaseFields}
|
release {
|
||||||
|
${releaseFields}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
totalCount
|
totalCount
|
||||||
}
|
}
|
||||||
@@ -153,7 +149,7 @@ function initEntitiesActions(store, router) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
entity: curateEntity(entity, null, connection.releases, { lastBatch: lastBatch?.id }),
|
entity: curateEntity(entity, null, connection.releases.map(({ release }) => release), { lastBatch: lastBatch?.id }),
|
||||||
totalCount: connection.totalCount,
|
totalCount: connection.totalCount,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,6 +97,13 @@ const actorFields = `
|
|||||||
${actorStashesFields}
|
${actorStashesFields}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const basicActorFields = `
|
||||||
|
id
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
gender
|
||||||
|
`;
|
||||||
|
|
||||||
const movieFields = `
|
const movieFields = `
|
||||||
id
|
id
|
||||||
title
|
title
|
||||||
@@ -240,6 +247,14 @@ const releaseActorsFragment = `
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const releaseBasicActorsFragment = `
|
||||||
|
actors: releasesActors(orderBy: ACTOR_BY_ACTOR_ID__GENDER_ASC) {
|
||||||
|
actor {
|
||||||
|
${basicActorFields}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
const releaseDirectorFragment = `
|
const releaseDirectorFragment = `
|
||||||
directors: releasesDirectors(orderBy: ACTOR_BY_DIRECTOR_ID__NAME_ASC) {
|
directors: releasesDirectors(orderBy: ACTOR_BY_DIRECTOR_ID__NAME_ASC) {
|
||||||
director {
|
director {
|
||||||
@@ -339,6 +354,31 @@ const releasePhotosFragment = `
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const releaseCapsFragment = `
|
||||||
|
caps: releasesCaps(orderBy: MEDIA_BY_MEDIA_ID__INDEX_ASC) {
|
||||||
|
media {
|
||||||
|
id
|
||||||
|
index
|
||||||
|
path
|
||||||
|
thumbnail
|
||||||
|
width
|
||||||
|
height
|
||||||
|
thumbnailWidth
|
||||||
|
thumbnailHeight
|
||||||
|
lazy
|
||||||
|
isS3
|
||||||
|
comment
|
||||||
|
sfw: sfwMedia {
|
||||||
|
id
|
||||||
|
thumbnail
|
||||||
|
lazy
|
||||||
|
path
|
||||||
|
comment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
const releaseTrailerFragment = `
|
const releaseTrailerFragment = `
|
||||||
trailer: releasesTrailer {
|
trailer: releasesTrailer {
|
||||||
media {
|
media {
|
||||||
@@ -379,11 +419,11 @@ const releaseFields = `
|
|||||||
createdAt
|
createdAt
|
||||||
url
|
url
|
||||||
createdBatchId
|
createdBatchId
|
||||||
${releaseActorsFragment}
|
${releaseBasicActorsFragment}
|
||||||
${releaseTagsFragment}
|
${releaseTagsFragment}
|
||||||
${releasePosterFragment}
|
${releasePosterFragment}
|
||||||
${releaseCoversFragment}
|
|
||||||
${releasePhotosFragment}
|
${releasePhotosFragment}
|
||||||
|
${releaseCapsFragment}
|
||||||
${siteFragment}
|
${siteFragment}
|
||||||
studio {
|
studio {
|
||||||
id
|
id
|
||||||
@@ -419,6 +459,7 @@ const releaseFields = `
|
|||||||
`;
|
`;
|
||||||
// isNew too performance-intensive
|
// isNew too performance-intensive
|
||||||
|
|
||||||
|
/*
|
||||||
const releasesFragment = `
|
const releasesFragment = `
|
||||||
connection: releasesConnection(
|
connection: releasesConnection(
|
||||||
filter: {
|
filter: {
|
||||||
@@ -447,6 +488,35 @@ const releasesFragment = `
|
|||||||
totalCount
|
totalCount
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
*/
|
||||||
|
|
||||||
|
const releasesFragment = `
|
||||||
|
connection: releasesSummariesConnection(
|
||||||
|
first: $limit
|
||||||
|
offset: $offset
|
||||||
|
orderBy: $orderBy
|
||||||
|
filter: {
|
||||||
|
or: [
|
||||||
|
{
|
||||||
|
not: { tags: { overlaps: $exclude } }
|
||||||
|
}
|
||||||
|
{
|
||||||
|
tags: { isNull: true }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
effectiveDate: { lessThan: $before, greaterThan: $after }
|
||||||
|
showcased: { equalTo: true }
|
||||||
|
batchShowcased: { in: $batchShowcased }
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
releases: nodes {
|
||||||
|
release {
|
||||||
|
${releaseFields}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
totalCount
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
const mediaFields = `
|
const mediaFields = `
|
||||||
id
|
id
|
||||||
@@ -475,6 +545,7 @@ const releaseFragment = `
|
|||||||
release(id: $releaseId) {
|
release(id: $releaseId) {
|
||||||
id
|
id
|
||||||
title
|
title
|
||||||
|
altTitles
|
||||||
description
|
description
|
||||||
date
|
date
|
||||||
datePrecision
|
datePrecision
|
||||||
@@ -482,6 +553,7 @@ const releaseFragment = `
|
|||||||
createdAt
|
createdAt
|
||||||
shootId
|
shootId
|
||||||
qualities
|
qualities
|
||||||
|
photoCount
|
||||||
productionDate
|
productionDate
|
||||||
createdBatchId
|
createdBatchId
|
||||||
productionLocation
|
productionLocation
|
||||||
@@ -499,6 +571,7 @@ const releaseFragment = `
|
|||||||
${releaseTagsFragment}
|
${releaseTagsFragment}
|
||||||
${releasePosterFragment}
|
${releasePosterFragment}
|
||||||
${releasePhotosFragment}
|
${releasePhotosFragment}
|
||||||
|
${releaseCapsFragment}
|
||||||
${releaseCoversFragment}
|
${releaseCoversFragment}
|
||||||
${releaseTrailerFragment}
|
${releaseTrailerFragment}
|
||||||
${releaseTeaserFragment}
|
${releaseTeaserFragment}
|
||||||
@@ -602,7 +675,11 @@ const releaseFragment = `
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const batchFragment = `
|
const batchFragment = `
|
||||||
batches(first: 1, orderBy: CREATED_AT_DESC) {
|
batches(
|
||||||
|
first: 1,
|
||||||
|
orderBy: CREATED_AT_DESC,
|
||||||
|
filter: { showcased: { equalTo: true } }
|
||||||
|
) {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -23,8 +23,9 @@ function initReleasesActions(store, router) {
|
|||||||
$offset:Int = 0,
|
$offset:Int = 0,
|
||||||
$after:Datetime = "1900-01-01 00:00:00",
|
$after:Datetime = "1900-01-01 00:00:00",
|
||||||
$before:Datetime = "2100-01-01 00:00:00",
|
$before:Datetime = "2100-01-01 00:00:00",
|
||||||
$orderBy: [ReleasesOrderBy!],
|
$orderBy: [ReleasesSummariesOrderBy!],
|
||||||
$exclude: [String!]
|
$exclude: [String!],
|
||||||
|
$batchShowcased: [Boolean!]
|
||||||
) {
|
) {
|
||||||
${releasesFragment}
|
${releasesFragment}
|
||||||
${batchFragment}
|
${batchFragment}
|
||||||
@@ -38,6 +39,7 @@ function initReleasesActions(store, router) {
|
|||||||
before,
|
before,
|
||||||
orderBy,
|
orderBy,
|
||||||
exclude: store.state.ui.tagFilter,
|
exclude: store.state.ui.tagFilter,
|
||||||
|
batchShowcased: range === 'new' ? true : [true, false],
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -15,19 +15,19 @@ function initTagsActions(store, _router) {
|
|||||||
}) {
|
}) {
|
||||||
const { before, after, orderBy } = getDateRange(range);
|
const { before, after, orderBy } = getDateRange(range);
|
||||||
|
|
||||||
const { tagBySlug, batches: [lastBatch] } = await graphql(`
|
const { tagBySlug, scenesConnection, batches: [lastBatch] } = await graphql(`
|
||||||
query Tag(
|
query Tag(
|
||||||
$tagSlug:String!
|
$tagSlug: String!
|
||||||
$offset: Int = 0,
|
$offset: Int = 0,
|
||||||
$limit:Int = 1000,
|
$limit:Int = 1000,
|
||||||
$after:Datetime = "1900-01-01",
|
$after:Datetime = "1900-01-01",
|
||||||
$before:Datetime = "2100-01-01",
|
$before:Datetime = "2100-01-01",
|
||||||
$orderBy: [ReleasesOrderBy!],
|
$orderBy: [ReleasesSummariesOrderBy!],
|
||||||
$exclude: [String!]
|
$exclude: [String!]
|
||||||
$hasAuth: Boolean!
|
$hasAuth: Boolean!
|
||||||
$userId: Int
|
$userId: Int
|
||||||
) {
|
) {
|
||||||
tagBySlug(slug:$tagSlug) {
|
tagBySlug(slug: $tagSlug) {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
slug
|
slug
|
||||||
@@ -155,32 +155,32 @@ function initTagsActions(store, _router) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scenesConnection(
|
}
|
||||||
filter: {
|
scenesConnection: releasesSummariesConnection(
|
||||||
effectiveDate: {
|
first: $limit
|
||||||
lessThan: $before,
|
offset: $offset
|
||||||
greaterThan: $after,
|
orderBy: $orderBy
|
||||||
},
|
filter: {
|
||||||
releasesTagsConnection: {
|
or: [
|
||||||
none: {
|
{
|
||||||
tag: {
|
not: { tags: { overlaps: $exclude } }
|
||||||
slug: {
|
}
|
||||||
in: $exclude
|
{
|
||||||
}
|
tags: { isNull: true }
|
||||||
}
|
}
|
||||||
}
|
]
|
||||||
}
|
tags: { anyEqualTo: $tagSlug }
|
||||||
},
|
effectiveDate: { lessThan: $before, greaterThan: $after }
|
||||||
first: $limit,
|
showcased: { equalTo: true }
|
||||||
orderBy: $orderBy,
|
}
|
||||||
offset: $offset
|
) {
|
||||||
) {
|
releases: nodes {
|
||||||
releases: nodes {
|
release {
|
||||||
${releaseFields}
|
${releaseFields}
|
||||||
}
|
}
|
||||||
totalCount
|
|
||||||
}
|
}
|
||||||
}
|
totalCount
|
||||||
|
}
|
||||||
${batchFragment}
|
${batchFragment}
|
||||||
}
|
}
|
||||||
`, {
|
`, {
|
||||||
@@ -197,8 +197,8 @@ function initTagsActions(store, _router) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
tag: curateTag(tagBySlug, null, curateRelease),
|
tag: curateTag(tagBySlug, null, curateRelease),
|
||||||
releases: tagBySlug.scenesConnection.releases.map((release) => curateRelease(release, 'scene', { lastBatch: lastBatch.id })),
|
releases: scenesConnection.releases.map(({ release }) => curateRelease(release, 'scene', { lastBatch: lastBatch.id })),
|
||||||
totalCount: tagBySlug.scenesConnection.totalCount,
|
totalCount: scenesConnection.totalCount,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ function initUiActions(store, _router) {
|
|||||||
${releaseFields}
|
${releaseFields}
|
||||||
}
|
}
|
||||||
alert {
|
alert {
|
||||||
|
all
|
||||||
tags: alertsTags {
|
tags: alertsTags {
|
||||||
tag {
|
tag {
|
||||||
id
|
id
|
||||||
@@ -82,7 +83,7 @@ function initUiActions(store, _router) {
|
|||||||
slug
|
slug
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
entity: alertsEntity {
|
entities: alertsEntities {
|
||||||
entity {
|
entity {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
@@ -90,6 +91,10 @@ function initUiActions(store, _router) {
|
|||||||
independent
|
independent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
matches: alertsMatches {
|
||||||
|
property
|
||||||
|
expression
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
totalCount
|
totalCount
|
||||||
@@ -259,7 +264,6 @@ function initUiActions(store, _router) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function fetchCampaign(context, campaignId) {
|
async function fetchCampaign(context, campaignId) {
|
||||||
console.log(campaignId);
|
|
||||||
const { campaign } = await graphql(`
|
const { campaign } = await graphql(`
|
||||||
query Campaign(
|
query Campaign(
|
||||||
$campaignId: Int!
|
$campaignId: Int!
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ function initUsersActions(store, _router) {
|
|||||||
id
|
id
|
||||||
notify
|
notify
|
||||||
email
|
email
|
||||||
|
all
|
||||||
stashes: alertsStashes {
|
stashes: alertsStashes {
|
||||||
stash {
|
stash {
|
||||||
id
|
id
|
||||||
@@ -85,12 +86,17 @@ function initUsersActions(store, _router) {
|
|||||||
slug
|
slug
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
matches: alertsMatches {
|
||||||
|
id
|
||||||
|
property
|
||||||
|
expression
|
||||||
|
}
|
||||||
actors: alertsActors {
|
actors: alertsActors {
|
||||||
actor {
|
actor {
|
||||||
${actorFields}
|
${actorFields}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
entity: alertsEntity {
|
entities: alertsEntities {
|
||||||
entity {
|
entity {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
|
|||||||
53
assets/maintenance/index.html
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width,height=device-height,initial-scale=1,maximum-scale=1,user-scalable=no">
|
||||||
|
<meta name="theme-color" content="#ff2288">
|
||||||
|
|
||||||
|
<title>traxxx | maintenance</title>
|
||||||
|
|
||||||
|
<link rel="icon" href="/img/favicon/favicon-32.ico">
|
||||||
|
<link rel="icon" href="/img/favicon/favicon.svg" type="image/svg+xml">
|
||||||
|
<link rel="apple-touch-icon" href="/img/favicon/favicon-180.png">
|
||||||
|
<link rel="manifest" href="/img/favicon/manifest.webmanifest">
|
||||||
|
|
||||||
|
<meta name="msapplication-TileColor" content="#aa2c66">
|
||||||
|
<meta name="msapplication-config" content="/img/favicon/browserconfig.xml">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body,
|
||||||
|
html {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-family: sans-serif;
|
||||||
|
background: url('/maintenance/maintenance_shay_evans_2.jpeg');
|
||||||
|
background-position: top center;
|
||||||
|
background-size: cover
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
padding: 2rem;
|
||||||
|
margin: 1rem;
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
text-shadow: 0 0 5px black;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: bold;
|
||||||
|
border-radius: 2rem;
|
||||||
|
backdrop-filter: blur(.5rem);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="text">Traxxx is currently under maintenance. We will be back shortly!</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
BIN
assets/maintenance/maintenance_ella_reese.jpeg
Executable file
|
After Width: | Height: | Size: 229 KiB |
BIN
assets/maintenance/maintenance_shay_evans.jpeg
Normal file
|
After Width: | Height: | Size: 324 KiB |
BIN
assets/maintenance/maintenance_shay_evans_2.jpeg
Normal file
|
After Width: | Height: | Size: 288 KiB |
BIN
assets/maintenance/maintenance_shay_evans_3.jpeg
Normal file
|
After Width: | Height: | Size: 273 KiB |
@@ -12,8 +12,20 @@ module.exports = {
|
|||||||
password: 'password',
|
password: 'password',
|
||||||
database: 'traxxx',
|
database: 'traxxx',
|
||||||
},
|
},
|
||||||
|
manticore: {
|
||||||
|
host: '127.0.0.1',
|
||||||
|
sqlPort: 9306,
|
||||||
|
httpPort: 9308,
|
||||||
|
},
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
graphiql: false,
|
graphiql: false,
|
||||||
|
pool: {
|
||||||
|
min: 0,
|
||||||
|
max: 20,
|
||||||
|
acquireTimeoutMillis: 300000,
|
||||||
|
createTimeoutMillis: 300000,
|
||||||
|
destroyTimeoutMillis: 300000,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
web: {
|
web: {
|
||||||
host: '0.0.0.0',
|
host: '0.0.0.0',
|
||||||
@@ -30,6 +42,20 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
redis: {
|
||||||
|
host: 'localhost',
|
||||||
|
port: 6379,
|
||||||
|
username: null,
|
||||||
|
password: null,
|
||||||
|
},
|
||||||
|
location: {
|
||||||
|
userAgent: 'contact via https://traxxx.me/',
|
||||||
|
},
|
||||||
|
analytics: {
|
||||||
|
enabled: false,
|
||||||
|
address: 'http://localhost:3000/script.js',
|
||||||
|
siteId: '1b28ac3b-d229-43bf-aec9-75cf0a72a466',
|
||||||
|
},
|
||||||
s3: {
|
s3: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
bucket: 'traxxx',
|
bucket: 'traxxx',
|
||||||
@@ -42,6 +68,9 @@ module.exports = {
|
|||||||
usernameLength: [2, 24],
|
usernameLength: [2, 24],
|
||||||
usernamePattern: /^[a-zA-Z0-9_-]+$/,
|
usernamePattern: /^[a-zA-Z0-9_-]+$/,
|
||||||
},
|
},
|
||||||
|
stashes: {
|
||||||
|
viewRefreshCooldown: 60, // minutes
|
||||||
|
},
|
||||||
exclude: {
|
exclude: {
|
||||||
channels: [
|
channels: [
|
||||||
// 21sextreme, no longer updated
|
// 21sextreme, no longer updated
|
||||||
@@ -57,6 +86,7 @@ module.exports = {
|
|||||||
'amberathome',
|
'amberathome',
|
||||||
'marycarey',
|
'marycarey',
|
||||||
'racqueldevonshire',
|
'racqueldevonshire',
|
||||||
|
'aziani',
|
||||||
// blowpass
|
// blowpass
|
||||||
'sunlustxxx',
|
'sunlustxxx',
|
||||||
// ddfnetwork
|
// ddfnetwork
|
||||||
@@ -360,7 +390,7 @@ module.exports = {
|
|||||||
thumbnailQuality: 100,
|
thumbnailQuality: 100,
|
||||||
lazySize: 90,
|
lazySize: 90,
|
||||||
lazyQuality: 90,
|
lazyQuality: 90,
|
||||||
trailerQuality: [480, 540, 360, 720, 960, 1080, 320, 1440, 1600, 1920, 2160, 270, 240, 180],
|
trailerQuality: [540, 720, 480, 360, 960, 1080, 320, 1440, 1600, 1920, 2160, 270, 240, 180],
|
||||||
limit: 25, // max number of photos per release
|
limit: 25, // max number of photos per release
|
||||||
attempts: 2,
|
attempts: 2,
|
||||||
fetchStreams: true,
|
fetchStreams: true,
|
||||||
|
|||||||
4
docs/puppeteer.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# Puppeteer
|
||||||
|
Puppeteer has several dependencies that may not be available in Debian 12 by default:
|
||||||
|
|
||||||
|
`apt install libasound2 libatk-bridge2.0-0 libcairo2 libcups2 libdrm2 libgbm-dev libpango-1.0-0 libxcomposite1 libxdamage1 libxfixes3 libxkbcommon-x11-0 libxrandr2 `
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// const config = require('config');
|
const config = require('config');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
apps: [
|
apps: [
|
||||||
@@ -14,5 +14,15 @@ module.exports = {
|
|||||||
NODE_ENV: 'production',
|
NODE_ENV: 'production',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
...(config.analytics.enabled ? [{
|
||||||
|
name: 'umami',
|
||||||
|
script: 'npm start',
|
||||||
|
cwd: process.env.UMAMI_DIR || '../umami',
|
||||||
|
restart_delay: 3000,
|
||||||
|
merge_logs: true,
|
||||||
|
env: {
|
||||||
|
NODE_ENV: 'production',
|
||||||
|
},
|
||||||
|
}] : []),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
47
migrations/20230709231430_release_summaries.js
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
const config = require('config');
|
||||||
|
|
||||||
|
exports.up = async (knex) => {
|
||||||
|
await knex.raw(`
|
||||||
|
CREATE MATERIALIZED VIEW releases_summaries AS (
|
||||||
|
SELECT
|
||||||
|
releases.id as release_id,
|
||||||
|
channels.slug as channel_slug,
|
||||||
|
channels.type as channel_type,
|
||||||
|
networks.slug as network_slug,
|
||||||
|
networks.type as network_type,
|
||||||
|
parent_networks.slug as parent_network_slug,
|
||||||
|
parent_networks.type as parent_network_type,
|
||||||
|
studios.showcased IS NOT false
|
||||||
|
AND (channels.showcased IS NOT false OR COALESCE(studios.showcased, false) = true)
|
||||||
|
AND (networks.showcased IS NOT false OR COALESCE(channels.showcased, false) = true OR COALESCE(studios.showcased, false) = true)
|
||||||
|
AS showcased,
|
||||||
|
batches.showcased AS batch_showcased,
|
||||||
|
releases.effective_date,
|
||||||
|
releases.created_at,
|
||||||
|
array_agg(tags.slug ORDER BY tags.priority DESC) FILTER (WHERE tags.slug IS NOT NULL) AS tags
|
||||||
|
FROM releases
|
||||||
|
LEFT JOIN releases_tags ON releases_tags.release_id = releases.id
|
||||||
|
LEFT JOIN tags ON tags.id = releases_tags.tag_id
|
||||||
|
LEFT JOIN entities AS channels ON channels.id = releases.entity_id
|
||||||
|
LEFT JOIN entities AS studios ON studios.id = releases.studio_id
|
||||||
|
LEFT JOIN entities AS networks ON networks.id = channels.parent_id
|
||||||
|
LEFT JOIN entities AS parent_networks ON parent_networks.id = networks.parent_id
|
||||||
|
LEFT JOIN batches ON batches.id = releases.updated_batch_id
|
||||||
|
GROUP BY releases.id, studios.showcased, batches.showcased,
|
||||||
|
channels.showcased, channels.slug, channels.type,
|
||||||
|
networks.showcased, networks.slug, networks.type,
|
||||||
|
parent_networks.slug, parent_networks.type
|
||||||
|
);
|
||||||
|
|
||||||
|
COMMENT ON MATERIALIZED VIEW releases_summaries IS E'@foreignKey (release_id) references releases (id)';
|
||||||
|
GRANT ALL ON releases_summaries TO :visitor;
|
||||||
|
`, {
|
||||||
|
visitor: knex.raw(config.database.query.user),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = async (knex) => {
|
||||||
|
await knex.raw(`
|
||||||
|
DROP MATERIALIZED VIEW IF EXISTS releases_summaries;
|
||||||
|
`);
|
||||||
|
};
|
||||||
27
migrations/20230723001912_actors_social_entity.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
exports.up = async (knex) => {
|
||||||
|
await knex.schema.alterTable('actors_social', (table) => {
|
||||||
|
table.integer('profile_id')
|
||||||
|
.references('id')
|
||||||
|
.inTable('actors_profiles');
|
||||||
|
|
||||||
|
table.dropUnique(['url', 'actor_id']);
|
||||||
|
table.unique(['url', 'actor_id', 'profile_id']);
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.raw(`
|
||||||
|
CREATE UNIQUE INDEX actors_social_url_actor_id_null_unique ON actors_social (url, actor_id) WHERE profile_id IS NULL;
|
||||||
|
`);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = async (knex) => {
|
||||||
|
await knex.raw(`
|
||||||
|
DROP INDEX actors_social_url_actor_id_null_unique;
|
||||||
|
`);
|
||||||
|
|
||||||
|
await knex.schema.alterTable('actors_social', (table) => {
|
||||||
|
table.dropUnique(['url', 'actor_id', 'profile_id']);
|
||||||
|
table.unique(['url', 'actor_id']);
|
||||||
|
|
||||||
|
table.dropColumn('profile_id');
|
||||||
|
});
|
||||||
|
};
|
||||||
24
migrations/20230725001453_caps.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
const config = require('config');
|
||||||
|
|
||||||
|
exports.up = async (knex) => {
|
||||||
|
await knex.schema.createTable('releases_caps', (table) => {
|
||||||
|
table.integer('release_id')
|
||||||
|
.notNullable()
|
||||||
|
.references('id')
|
||||||
|
.inTable('releases')
|
||||||
|
.onDelete('cascade');
|
||||||
|
|
||||||
|
table.text('media_id')
|
||||||
|
.notNullable()
|
||||||
|
.references('id')
|
||||||
|
.inTable('media');
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.raw('GRANT ALL ON releases_caps TO :visitor;', {
|
||||||
|
visitor: knex.raw(config.database.query.user),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = async (knex) => {
|
||||||
|
await knex.schema.dropTable('releases_caps');
|
||||||
|
};
|
||||||
27
migrations/20230725020639_blood_type.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
exports.up = async (knex) => {
|
||||||
|
await knex.schema.alterTable('actors_profiles', (table) => {
|
||||||
|
table.string('hair_type');
|
||||||
|
table.decimal('shoe_size');
|
||||||
|
table.string('blood_type');
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.schema.alterTable('actors', (table) => {
|
||||||
|
table.string('hair_type');
|
||||||
|
table.decimal('shoe_size');
|
||||||
|
table.string('blood_type');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = async (knex) => {
|
||||||
|
await knex.schema.alterTable('actors_profiles', (table) => {
|
||||||
|
table.dropColumn('hair_type');
|
||||||
|
table.dropColumn('shoe_size');
|
||||||
|
table.dropColumn('blood_type');
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.schema.alterTable('actors', (table) => {
|
||||||
|
table.dropColumn('hair_type');
|
||||||
|
table.dropColumn('shoe_size');
|
||||||
|
table.dropColumn('blood_type');
|
||||||
|
});
|
||||||
|
};
|
||||||
13
migrations/20230725031547_stealth_batch.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
exports.up = async (knex) => {
|
||||||
|
await knex.schema.alterTable('batches', (table) => {
|
||||||
|
table.boolean('showcased')
|
||||||
|
.notNullable()
|
||||||
|
.defaultTo(true);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = async (knex) => {
|
||||||
|
await knex.schema.alterTable('batches', (table) => {
|
||||||
|
table.dropColumn('showcased');
|
||||||
|
});
|
||||||
|
};
|
||||||
27
migrations/20230801225038_scene_titles.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
exports.up = async (knex) => {
|
||||||
|
await knex.schema.alterTable('releases', (table) => {
|
||||||
|
table.specificType('alt_titles', 'text ARRAY');
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.schema.alterTable('movies', (table) => {
|
||||||
|
table.specificType('alt_titles', 'text ARRAY');
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.schema.alterTable('series', (table) => {
|
||||||
|
table.specificType('alt_titles', 'text ARRAY');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = async (knex) => {
|
||||||
|
await knex.schema.alterTable('releases', (table) => {
|
||||||
|
table.dropColumn('alt_titles');
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.schema.alterTable('movies', (table) => {
|
||||||
|
table.dropColumn('alt_titles');
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.schema.alterTable('series', (table) => {
|
||||||
|
table.dropColumn('alt_titles');
|
||||||
|
});
|
||||||
|
};
|
||||||
36
migrations/20230811015424_teasers.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
exports.up = async (knex) => {
|
||||||
|
await knex.schema.createTable('movies_teasers', (table) => {
|
||||||
|
table.integer('movie_id', 16)
|
||||||
|
.notNullable()
|
||||||
|
.references('id')
|
||||||
|
.inTable('movies')
|
||||||
|
.onDelete('cascade');
|
||||||
|
|
||||||
|
table.text('media_id', 21)
|
||||||
|
.notNullable()
|
||||||
|
.references('id')
|
||||||
|
.inTable('media');
|
||||||
|
|
||||||
|
table.unique('movie_id');
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.schema.createTable('series_teasers', (table) => {
|
||||||
|
table.integer('serie_id', 16)
|
||||||
|
.notNullable()
|
||||||
|
.references('id')
|
||||||
|
.inTable('series')
|
||||||
|
.onDelete('cascade');
|
||||||
|
|
||||||
|
table.text('media_id', 21)
|
||||||
|
.notNullable()
|
||||||
|
.references('id')
|
||||||
|
.inTable('media');
|
||||||
|
|
||||||
|
table.unique('serie_id');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = async (knex) => {
|
||||||
|
await knex.schema.dropTable('movies_teasers');
|
||||||
|
await knex.schema.dropTable('series_teasers');
|
||||||
|
};
|
||||||
19
migrations/20231107044032_photocount.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
exports.up = async (knex) => {
|
||||||
|
await knex.schema.alterTable('releases', (table) => {
|
||||||
|
table.integer('photo_count');
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.schema.alterTable('movies', (table) => {
|
||||||
|
table.integer('photo_count');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = async (knex) => {
|
||||||
|
await knex.schema.alterTable('releases', (table) => {
|
||||||
|
table.dropColumn('photo_count');
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.schema.alterTable('movies', (table) => {
|
||||||
|
table.dropColumn('photo_count');
|
||||||
|
});
|
||||||
|
};
|
||||||
42
migrations/20231109011513_alert_andor_pattern.js
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
const config = require('config');
|
||||||
|
|
||||||
|
exports.up = async (knex) => {
|
||||||
|
await knex.schema.alterTable('alerts', (table) => {
|
||||||
|
table.boolean('all')
|
||||||
|
.defaultTo(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.schema.alterTable('alerts_entities', (table) => {
|
||||||
|
table.dropUnique('alert_id');
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.schema.createTable('alerts_matches', (table) => {
|
||||||
|
table.increments('id');
|
||||||
|
|
||||||
|
table.integer('alert_id')
|
||||||
|
.references('id')
|
||||||
|
.inTable('alerts')
|
||||||
|
.onDelete('cascade');
|
||||||
|
|
||||||
|
table.string('property');
|
||||||
|
table.string('expression');
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.raw(`
|
||||||
|
GRANT SELECT ON alerts_matches TO :visitor;
|
||||||
|
`, {
|
||||||
|
visitor: knex.raw(config.database.query.user),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = async (knex) => {
|
||||||
|
await knex.schema.alterTable('alerts', (table) => {
|
||||||
|
table.dropColumn('all');
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.schema.alterTable('alerts_entities', (table) => {
|
||||||
|
table.unique('alert_id');
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.schema.dropTable('alerts_matches');
|
||||||
|
};
|
||||||
21
migrations/20231201040310_tagsplit.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
exports.up = async (knex) => {
|
||||||
|
await knex.schema.alterTable('tags', (table) => {
|
||||||
|
table.specificType('implied_tag_ids', 'integer[]');
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.schema.alterTable('releases_tags', (table) => {
|
||||||
|
table.enum('source', ['scraper', 'editor', 'implied'])
|
||||||
|
.notNullable()
|
||||||
|
.defaultTo('scraper');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = async (knex) => {
|
||||||
|
await knex.schema.alterTable('tags', (table) => {
|
||||||
|
table.dropColumn('implied_tag_ids');
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.schema.alterTable('releases_tags', (table) => {
|
||||||
|
table.dropColumn('source');
|
||||||
|
});
|
||||||
|
};
|
||||||
19
migrations/20231216015820_movies_series_photo_count.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
exports.up = async (knex) => {
|
||||||
|
await knex.schema.alterTable('movies', (table) => {
|
||||||
|
table.integer('photo_count');
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.schema.alterTable('series', (table) => {
|
||||||
|
table.integer('photo_count');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = async (knex) => {
|
||||||
|
await knex.schema.alterTable('movies', (table) => {
|
||||||
|
table.dropColumn('photo_count');
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.schema.alterTable('series', (table) => {
|
||||||
|
table.dropColumn('photo_count');
|
||||||
|
});
|
||||||
|
};
|
||||||
34
migrations/20240104234936_actors_metadata.js
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
exports.up = async function up(knex) {
|
||||||
|
await knex.raw(`
|
||||||
|
CREATE MATERIALIZED VIEW actors_meta AS (
|
||||||
|
SELECT
|
||||||
|
actors.*,
|
||||||
|
COUNT(DISTINCT stashes_actors) as stashed,
|
||||||
|
COUNT(DISTINCT releases_actors) as scenes,
|
||||||
|
row_to_json(avatars) as avatar
|
||||||
|
FROM actors
|
||||||
|
LEFT JOIN stashes_actors ON stashes_actors.actor_id = actors.id
|
||||||
|
LEFT JOIN releases_actors ON releases_actors.actor_id = actors.id
|
||||||
|
LEFT JOIN media AS avatars ON avatars.id = actors.avatar_media_id
|
||||||
|
GROUP BY
|
||||||
|
actors.id,
|
||||||
|
avatars.id
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE MATERIALIZED VIEW scenes_meta AS (
|
||||||
|
SELECT
|
||||||
|
releases.*,
|
||||||
|
COUNT(DISTINCT stashes_scenes) as stashed
|
||||||
|
FROM releases
|
||||||
|
LEFT JOIN stashes_scenes ON stashes_scenes.scene_id = releases.id
|
||||||
|
GROUP BY releases.id
|
||||||
|
);
|
||||||
|
`);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = async function down(knex) {
|
||||||
|
await knex.raw(`
|
||||||
|
DROP MATERIALIZED VIEW IF EXISTS actors_meta;
|
||||||
|
DROP MATERIALIZED VIEW IF EXISTS scenes_meta;
|
||||||
|
`);
|
||||||
|
};
|
||||||
36
migrations/20240125011700_manticore.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
const config = require('config');
|
||||||
|
const manticore = require('manticoresearch');
|
||||||
|
|
||||||
|
const mantiClient = new manticore.ApiClient();
|
||||||
|
|
||||||
|
mantiClient.basePath = `http://${config.database.manticore.host}:${config.database.manticore.httpPort}`;
|
||||||
|
|
||||||
|
const utilsApi = new manticore.UtilsApi(mantiClient);
|
||||||
|
|
||||||
|
exports.up = async () => {
|
||||||
|
await utilsApi.sql(`create table scenes (
|
||||||
|
id int,
|
||||||
|
title text,
|
||||||
|
title_filtered text,
|
||||||
|
shoot_id 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,
|
||||||
|
stashed int
|
||||||
|
)`);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = async () => {
|
||||||
|
await utilsApi.sql('drop table scenes');
|
||||||
|
};
|
||||||
31813
package-lock.json
generated
Executable file → Normal file
163
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "traxxx",
|
"name": "traxxx",
|
||||||
"version": "1.228.33",
|
"version": "1.236.1",
|
||||||
"description": "All the latest porn releases in one place",
|
"description": "All the latest porn releases in one place",
|
||||||
"main": "src/app.js",
|
"main": "src/app.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -38,103 +38,126 @@
|
|||||||
"author": "DebaucheryLibrarian",
|
"author": "DebaucheryLibrarian",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.12.10",
|
"@babel/cli": "^7.23.4",
|
||||||
"@babel/core": "^7.8.4",
|
"@babel/core": "^7.23.3",
|
||||||
"@babel/eslint-parser": "^7.16.0",
|
"@babel/eslint-parser": "^7.23.3",
|
||||||
"@babel/plugin-proposal-optional-chaining": "^7.8.3",
|
"@babel/plugin-proposal-optional-chaining": "^7.8.3",
|
||||||
"@babel/preset-env": "^7.8.4",
|
"@babel/preset-env": "^7.23.3",
|
||||||
"@babel/register": "^7.8.3",
|
"@babel/register": "^7.22.15",
|
||||||
"autoprefixer": "^10.4.0",
|
"autoprefixer": "^10.4.16",
|
||||||
"babel-loader": "^8.0.6",
|
"babel-loader": "^9.1.3",
|
||||||
"babel-preset-airbnb": "^5.0.0",
|
"babel-preset-airbnb": "^5.0.0",
|
||||||
"css-loader": "^6.5.0",
|
"css-loader": "^6.8.1",
|
||||||
"eslint": "^8.44.0",
|
"eslint": "^8.54.0",
|
||||||
"eslint-config-airbnb": "^19.0.4",
|
"eslint-config-airbnb": "^19.0.4",
|
||||||
"eslint-config-airbnb-base": "^15.0.0",
|
"eslint-config-airbnb-base": "^15.0.0",
|
||||||
"eslint-plugin-import": "^2.20.1",
|
"eslint-plugin-import": "^2.29.0",
|
||||||
"eslint-plugin-jsx-a11y": "^6.2.3",
|
"eslint-plugin-jsx-a11y": "^6.8.0",
|
||||||
"eslint-plugin-react": "^7.18.3",
|
"eslint-plugin-react": "^7.33.2",
|
||||||
"eslint-plugin-vue": "^8.0.3",
|
"eslint-plugin-vue": "^9.18.1",
|
||||||
"eslint-watch": "^8.0.0",
|
"eslint-watch": "^8.0.0",
|
||||||
"eslint-webpack-plugin": "^3.1.0",
|
"eslint-webpack-plugin": "^4.0.1",
|
||||||
"mini-css-extract-plugin": "^2.4.3",
|
"mini-css-extract-plugin": "^2.7.6",
|
||||||
"node-sass": "^6.0.1",
|
"node-sass": "^9.0.0",
|
||||||
"postcss-loader": "^6.2.0",
|
"postcss-loader": "^7.3.3",
|
||||||
"raw-loader": "^4.0.2",
|
"raw-loader": "^4.0.2",
|
||||||
"sass-loader": "^12.3.0",
|
"sass-loader": "^13.3.2",
|
||||||
"vue-loader": "^16.8.2",
|
"style-loader": "^3.3.3",
|
||||||
"webpack": "^5.11.0",
|
"vue-loader": "^17.3.1",
|
||||||
"webpack-cli": "^4.9.1"
|
"webpack": "^5.89.0",
|
||||||
|
"webpack-cli": "^5.1.4"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@graphile-contrib/pg-order-by-related": "^1.0.0-beta.6",
|
"@aws-sdk/client-s3": "^3.458.0",
|
||||||
|
"@aws-sdk/credential-provider-ini": "^3.458.0",
|
||||||
|
"@aws-sdk/lib-storage": "^3.458.0",
|
||||||
|
"@casl/ability": "^6.5.0",
|
||||||
|
"@faker-js/faker": "^8.3.1",
|
||||||
|
"@graphile-contrib/pg-order-by-related": "^1.0.0",
|
||||||
"@graphile-contrib/pg-simplify-inflector": "^6.1.0",
|
"@graphile-contrib/pg-simplify-inflector": "^6.1.0",
|
||||||
"array-equal": "^1.0.0",
|
"@graphile/pg-aggregates": "^0.1.1",
|
||||||
"aws-sdk": "^2.847.0",
|
"acorn": "^8.11.2",
|
||||||
|
"array-equal": "^1.0.2",
|
||||||
"babel-polyfill": "^6.26.0",
|
"babel-polyfill": "^6.26.0",
|
||||||
"bhttp": "^1.2.8",
|
"bhttp": "^1.2.8",
|
||||||
"blake2": "^4.0.0",
|
"blake2": "^5.0.0",
|
||||||
"bluebird": "^3.7.2",
|
"bluebird": "^3.7.2",
|
||||||
|
"body-parser": "^1.20.2",
|
||||||
"bottleneck": "^2.19.5",
|
"bottleneck": "^2.19.5",
|
||||||
"canvas": "^2.11.2",
|
"canvas": "^2.11.2",
|
||||||
"casual": "^1.6.2",
|
"casual": "^1.6.2",
|
||||||
"cheerio": "^1.0.0-rc.3",
|
"cheerio": "^1.0.0-rc.12",
|
||||||
"cli-confirm": "^1.0.1",
|
"cli-confirm": "^1.0.1",
|
||||||
"config": "^3.2.5",
|
"cloudscraper": "^4.6.0",
|
||||||
"connect-session-knex": "^2.0.0",
|
"config": "^3.3.9",
|
||||||
"convert": "^4.2.4",
|
"connect-session-knex": "^4.0.0",
|
||||||
"cookie": "^0.4.0",
|
"convert": "^4.14.0",
|
||||||
"csv-stringify": "^5.3.6",
|
"cookie": "^0.6.0",
|
||||||
|
"csv-stringify": "^6.4.4",
|
||||||
"date-fns": "^2.30.0",
|
"date-fns": "^2.30.0",
|
||||||
"dayjs": "^1.8.21",
|
"dayjs": "^1.11.10",
|
||||||
"dompurify": "^2.0.11",
|
"dompurify": "^3.0.6",
|
||||||
"ejs": "^3.0.1",
|
"ejs": "^3.1.9",
|
||||||
"express": "^4.17.1",
|
"escape-string-regexp": "^4.0.0",
|
||||||
"express-promise-router": "^4.1.0",
|
"express": "^4.18.2",
|
||||||
"express-session": "^1.17.1",
|
"express-promise-router": "^4.1.1",
|
||||||
|
"express-query-boolean": "^2.0.0",
|
||||||
|
"express-react-views": "^0.11.0",
|
||||||
|
"express-session": "^1.17.3",
|
||||||
"face-api.js": "^0.22.2",
|
"face-api.js": "^0.22.2",
|
||||||
"faker": "^5.1.0",
|
"file-type": "^18.7.0",
|
||||||
"file-type": "^16.5.3",
|
|
||||||
"fluent-ffmpeg": "^2.1.2",
|
"fluent-ffmpeg": "^2.1.2",
|
||||||
"fs-extra": "^10.0.0",
|
"fs-extra": "^11.1.1",
|
||||||
"graphile-utils": "^4.12.2",
|
"graphile-build": "^4.14.0",
|
||||||
"graphql": "^15.4.0",
|
"graphile-utils": "^4.14.0",
|
||||||
"html-entities": "^2.3.2",
|
"graphql": "^15.8.0",
|
||||||
|
"html-entities": "^2.4.0",
|
||||||
"iconv-lite": "^0.6.3",
|
"iconv-lite": "^0.6.3",
|
||||||
"inquirer": "^8.2.0",
|
"inquirer": "^8.2.6",
|
||||||
"inspector-api": "^1.4.2",
|
"inspector-api": "^1.4.8",
|
||||||
"jsdom": "^18.0.0",
|
"jsdom": "^23.0.1",
|
||||||
"knex": "^0.95.12",
|
"knex": "^3.0.1",
|
||||||
"knex-migrate": "^1.7.4",
|
"knex-migrate": "^1.7.4",
|
||||||
"mime": "^2.4.4",
|
"longjohn": "^0.2.12",
|
||||||
"moment": "^2.24.0",
|
"manticoresearch": "^4.0.0",
|
||||||
"nanoid": "^3.1.30",
|
"merge-anything": "^5.1.7",
|
||||||
"node-fetch": "^2.6.7",
|
"mime": "^3.0.0",
|
||||||
|
"mitt": "^3.0.1",
|
||||||
|
"moment": "^2.29.4",
|
||||||
|
"mysql": "^2.18.1",
|
||||||
|
"nanoid": "^3.3.7",
|
||||||
|
"node-fetch": "^3.3.2",
|
||||||
"object-merge-advanced": "^12.1.0",
|
"object-merge-advanced": "^12.1.0",
|
||||||
"object.omit": "^3.0.0",
|
"object.omit": "^3.0.0",
|
||||||
"pg": "^8.5.1",
|
"pg": "^8.11.3",
|
||||||
"postgraphile": "^4.13.0",
|
"postgraphile": "^4.14.0",
|
||||||
"postgraphile-plugin-connection-filter": "^2.2.2",
|
"postgraphile-plugin-connection-filter": "^2.3.0",
|
||||||
"promise-task-queue": "^1.2.0",
|
"promise-task-queue": "^1.2.0",
|
||||||
"puppeteer": "^20.5.0",
|
"prop-types": "^15.8.1",
|
||||||
|
"puppeteer": "^21.5.2",
|
||||||
"puppeteer-extra": "^3.3.6",
|
"puppeteer-extra": "^3.3.6",
|
||||||
"puppeteer-extra-plugin-stealth": "^2.11.2",
|
"puppeteer-extra-plugin-stealth": "^2.11.2",
|
||||||
"sharp": "^0.29.2",
|
"redis": "^4.6.11",
|
||||||
"showdown": "^1.9.1",
|
"sharp": "^0.33.0-rc.2",
|
||||||
"source-map-support": "^0.5.16",
|
"showdown": "^2.1.0",
|
||||||
|
"source-map-support": "^0.5.21",
|
||||||
"template-format": "^1.2.5",
|
"template-format": "^1.2.5",
|
||||||
"tough-cookie": "^4.0.0",
|
"tippy.js": "^6.3.7",
|
||||||
|
"tough-cookie": "^4.1.3",
|
||||||
"tunnel": "0.0.6",
|
"tunnel": "0.0.6",
|
||||||
"ua-parser-js": "^1.0.32",
|
"ua-parser-js": "^1.0.37",
|
||||||
"unprint": "^0.10.1",
|
"undici": "^5.28.1",
|
||||||
|
"unprint": "^0.10.11",
|
||||||
"url-pattern": "^1.0.3",
|
"url-pattern": "^1.0.3",
|
||||||
"v-tooltip": "^2.0.3",
|
"v-tooltip": "^2.1.3",
|
||||||
"vue": "^3.2.20",
|
"video.js": "^8.6.1",
|
||||||
"vue-router": "^4.0.12",
|
"videojs-vr": "^2.0.0",
|
||||||
"vuex": "^4.0.2",
|
"vue": "^3.3.9",
|
||||||
"why-is-node-running": "^2.2.0",
|
"vue-router": "^4.2.5",
|
||||||
"winston": "^3.2.1",
|
"vuex": "^4.1.0",
|
||||||
"winston-daily-rotate-file": "^4.4.2",
|
"why-is-node-running": "^2.2.2",
|
||||||
"yargs": "^17.2.1"
|
"winston": "^3.11.0",
|
||||||
|
"winston-daily-rotate-file": "^4.7.1",
|
||||||
|
"yargs": "^17.7.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.3 KiB |
BIN
public/img/logos/analvids/lazy/analvids.png
Executable file → Normal file
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 4.5 KiB |
BIN
public/img/logos/analvids/lazy/favicon.png
Executable file → Normal file
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
BIN
public/img/logos/analvids/lazy/favicon_dark.png
Executable file → Normal file
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
BIN
public/img/logos/analvids/lazy/favicon_light.png
Executable file → Normal file
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
BIN
public/img/logos/analvids/lazy/legalporno.png
Executable file → Normal file
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.6 KiB |
BIN
public/img/logos/analvids/lazy/network.png
Executable file → Normal file
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 4.5 KiB |
BIN
public/img/logos/analvids/misc/anal-vids.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
public/img/logos/analvids/misc/legal-porno-anal-vids.png
Executable file
|
After Width: | Height: | Size: 19 KiB |
BIN
public/img/logos/analvids/misc/legal-porno_favicon_dark.png
Executable file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
public/img/logos/analvids/misc/legal-porno_favicon_light.png
Executable file
|
After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 29 KiB |
BIN
public/img/logos/analvids/thumbs/analvids.png
Executable file → Normal file
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 8.8 KiB |
BIN
public/img/logos/analvids/thumbs/favicon.png
Executable file → Normal file
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
BIN
public/img/logos/analvids/thumbs/favicon_dark.png
Executable file → Normal file
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
BIN
public/img/logos/analvids/thumbs/favicon_light.png
Executable file → Normal file
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
BIN
public/img/logos/analvids/thumbs/legalporno.png
Executable file → Normal file
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
BIN
public/img/logos/analvids/thumbs/network.png
Executable file → Normal file
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 8.8 KiB |
BIN
public/img/logos/asiam/asiam.png
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
public/img/logos/asiam/favicon.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
public/img/logos/asiam/favicon_dark.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
public/img/logos/asiam/favicon_light.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
public/img/logos/asiam/lazy/asiam.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
public/img/logos/asiam/lazy/favicon.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
public/img/logos/asiam/lazy/favicon_dark.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
public/img/logos/asiam/lazy/favicon_light.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
public/img/logos/asiam/lazy/network.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
public/img/logos/asiam/misc/asia-m-mm.png
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
public/img/logos/asiam/network.png
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
public/img/logos/asiam/thumbs/asiam.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
public/img/logos/asiam/thumbs/favicon.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
public/img/logos/asiam/thumbs/favicon_dark.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
public/img/logos/asiam/thumbs/favicon_light.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
public/img/logos/asiam/thumbs/network.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
public/img/logos/aylo/aylo.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
public/img/logos/aylo/favicon.png
Executable file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
public/img/logos/aylo/favicon_dark.png
Executable file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
public/img/logos/aylo/favicon_light.png
Executable file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
public/img/logos/aylo/lazy/aylo.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
public/img/logos/aylo/lazy/favicon.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
public/img/logos/aylo/lazy/favicon_dark.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
public/img/logos/aylo/lazy/favicon_light.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
public/img/logos/aylo/lazy/network.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |