Merge branch 'master' into experimental
|
@ -17,10 +17,11 @@
|
|||
"vue/html-indent": ["error", "tab"],
|
||||
"vue/multiline-html-element-content-newline": 0,
|
||||
"vue/singleline-html-element-content-newline": 0,
|
||||
"vue/multi-word-component-names": 0,
|
||||
"no-param-reassign": ["error", {
|
||||
"props": true,
|
||||
"ignorePropertyModificationsFor": ["state", "acc"]
|
||||
}],
|
||||
}]
|
||||
},
|
||||
"globals": {
|
||||
"CONFIG": true
|
||||
|
|
|
@ -2,6 +2,7 @@ node_modules/
|
|||
dist/
|
||||
log/
|
||||
media/
|
||||
html/
|
||||
public/js/*
|
||||
public/css/*
|
||||
config/*
|
||||
|
@ -9,3 +10,4 @@ config/*
|
|||
assets/js/config/
|
||||
!assets/js/config/default.js
|
||||
*.heapprofile
|
||||
*.heapsnapshot
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<div class="actor-header">
|
||||
<h2 class="header-name">
|
||||
<span v-if="actor.entity">{{ actor.name }} ({{ actor.entity.name }})</span>
|
||||
<span v-else="">{{ actor.name }}</span>
|
||||
<span v-else>{{ actor.name }}</span>
|
||||
|
||||
<Gender
|
||||
:gender="actor.gender"
|
||||
|
|
|
@ -272,7 +272,7 @@ import Pagination from '../pagination/pagination.vue';
|
|||
|
||||
const toggleValues = [true, null, false];
|
||||
const boobSizes = 'ABCDEFGHIJKZ'.split('');
|
||||
const topCountries = ['AU', 'BR', 'DE', 'JP', 'RU', 'GB', 'US'];
|
||||
const topCountries = ['AU', 'BR', 'CZ', 'DE', 'JP', 'RU', 'GB', 'US'];
|
||||
|
||||
function updateFilters() {
|
||||
this.$router.push({
|
||||
|
|
|
@ -313,8 +313,8 @@ export default {
|
|||
}
|
||||
|
||||
.stash {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
padding: .25rem .25rem .5rem .5rem;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
/>
|
||||
</li>
|
||||
|
||||
<template v-slot:tooltip>
|
||||
<template #tooltip>
|
||||
<Search
|
||||
content="actors"
|
||||
@select="actor => addActor(actor)"
|
||||
|
@ -88,7 +88,7 @@
|
|||
/>
|
||||
</li>
|
||||
|
||||
<template v-slot:tooltip>
|
||||
<template #tooltip>
|
||||
<Search
|
||||
content="tags"
|
||||
:defaults="['anal', 'blowbang', 'mfm', 'dp', 'gangbang', 'airtight']"
|
||||
|
@ -126,7 +126,7 @@
|
|||
/>
|
||||
</div>
|
||||
|
||||
<template v-slot:tooltip>
|
||||
<template #tooltip>
|
||||
<Search
|
||||
label="Search channels"
|
||||
content="entities"
|
||||
|
@ -181,7 +181,7 @@
|
|||
/>
|
||||
</li>
|
||||
|
||||
<template v-slot:tooltip>
|
||||
<template #tooltip>
|
||||
<Search
|
||||
content="stashes"
|
||||
@select="stash => addStash(stash)"
|
||||
|
@ -194,6 +194,7 @@
|
|||
|
||||
<div class="dialog-actions right">
|
||||
<button
|
||||
:disabled="actors.length === 0 && tags.length === 0 && !entity"
|
||||
type="submit"
|
||||
class="button button-primary"
|
||||
>Add alert</button>
|
||||
|
@ -210,19 +211,19 @@ import Search from './search.vue';
|
|||
|
||||
async function addAlert() {
|
||||
await this.$store.dispatch('addAlert', {
|
||||
actors: this.actors.map(actor => actor.id),
|
||||
tags: this.tags.map(tag => tag.id),
|
||||
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),
|
||||
stashes: this.stashes.map((stash) => stash.id),
|
||||
});
|
||||
|
||||
this.$emit('close', true);
|
||||
}
|
||||
|
||||
function addActor(actor) {
|
||||
if (!this.actors.some(selectedActor => selectedActor.id === actor.id)) {
|
||||
if (!this.actors.some((selectedActor) => selectedActor.id === actor.id)) {
|
||||
this.actors = this.actors.concat(actor);
|
||||
}
|
||||
|
||||
|
@ -235,7 +236,7 @@ function addEntity(entity) {
|
|||
}
|
||||
|
||||
function addTag(tag) {
|
||||
if (!this.tags.some(selectedTag => selectedTag.id === tag.id)) {
|
||||
if (!this.tags.some((selectedTag) => selectedTag.id === tag.id)) {
|
||||
this.tags = this.tags.concat(tag);
|
||||
}
|
||||
|
||||
|
@ -243,7 +244,7 @@ function addTag(tag) {
|
|||
}
|
||||
|
||||
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() {
|
||||
|
@ -251,11 +252,11 @@ function removeEntity() {
|
|||
}
|
||||
|
||||
function removeTag(tag) {
|
||||
this.tags = this.tags.filter(listedTag => listedTag.id !== tag.id);
|
||||
this.tags = this.tags.filter((listedTag) => listedTag.id !== tag.id);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -263,7 +264,7 @@ function addStash(stash) {
|
|||
}
|
||||
|
||||
function removeStash(stash) {
|
||||
this.stashes = this.stashes.filter(listedStash => listedStash.id !== stash.id);
|
||||
this.stashes = this.stashes.filter((listedStash) => listedStash.id !== stash.id);
|
||||
}
|
||||
|
||||
export default {
|
||||
|
@ -273,6 +274,7 @@ export default {
|
|||
Entity,
|
||||
Search,
|
||||
},
|
||||
emits: ['close'],
|
||||
data() {
|
||||
return {
|
||||
actors: [],
|
||||
|
@ -284,7 +286,6 @@ export default {
|
|||
availableStashes: this.$store.state.auth.user.stashes,
|
||||
};
|
||||
},
|
||||
emits: ['close'],
|
||||
methods: {
|
||||
addActor,
|
||||
addAlert,
|
||||
|
|
|
@ -62,7 +62,7 @@ async function setConsent(consent, includeQueer) {
|
|||
}
|
||||
|
||||
if (includeQueer) {
|
||||
this.$store.dispatch('setTagFilter', this.$store.state.ui.tagFilter.filter(tag => !['gay', 'bisexual', 'transsexual'].includes(tag)));
|
||||
this.$store.dispatch('setTagFilter', this.$store.state.ui.tagFilter.filter((tag) => !['gay', 'bisexual', 'transsexual'].includes(tag)));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -108,6 +108,7 @@
|
|||
:fetch-releases="fetchEntity"
|
||||
:items-total="totalCount"
|
||||
:items-per-page="limit"
|
||||
:available-tags="entity.tags"
|
||||
/>
|
||||
|
||||
<div class="releases">
|
||||
|
@ -153,8 +154,8 @@ async function fetchEntity(scroll = true) {
|
|||
|
||||
this.pageTitle = entity.name;
|
||||
|
||||
const campaign = entity.campaigns.find(campaignX => !campaignX.banner)
|
||||
|| entity.parent?.campaigns.find(campaignX => !campaignX.banner);
|
||||
const campaign = entity.campaigns.find((campaignX) => !campaignX.banner)
|
||||
|| entity.parent?.campaigns.find((campaignX) => !campaignX.banner);
|
||||
|
||||
const affiliateParams = new URLSearchParams({
|
||||
...(entity.url && Object.fromEntries(new URL(entity.url).searchParams)), // preserve any query in entity URL, e.g. ?siteId=5
|
||||
|
|
|
@ -41,9 +41,10 @@
|
|||
</div>
|
||||
|
||||
<span
|
||||
v-if="entity.childrenTotal > 0 || typeof entity.sceneTotal !== 'undefined'"
|
||||
class="count"
|
||||
>
|
||||
<span>{{ 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>
|
||||
</router-link>
|
||||
|
@ -78,9 +79,10 @@ export default {
|
|||
box-shadow: 0 0 3px rgba(0, 0, 0, .25);
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
overflow: hidden;
|
||||
|
||||
&:hover .count {
|
||||
color: var(--lighten);
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,6 +102,8 @@ export default {
|
|||
}
|
||||
|
||||
.name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: var(--text-light);
|
||||
font-size: 1.25rem;
|
||||
font-weight: bold;
|
||||
|
@ -109,11 +113,15 @@ export default {
|
|||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: -1.75rem;
|
||||
box-sizing: border-box;
|
||||
padding: .25rem .5rem;
|
||||
border-top: solid 1px var(--lighten-hint);
|
||||
color: var(--lighten-weak);
|
||||
background: var(--darken-strong);
|
||||
box-shadow: 0 0 3px var(--darken);
|
||||
color: var(--text-light);
|
||||
text-align: center;
|
||||
font-size: .8rem;
|
||||
text-shadow: 1px 1px var(--darken);
|
||||
transition: bottom .1s ease;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -18,19 +18,16 @@
|
|||
<div class="filters">
|
||||
<ActorFilter
|
||||
class="filters-filter"
|
||||
:filter="filter"
|
||||
:available-actors="availableActors"
|
||||
/>
|
||||
|
||||
<ChannelFilter
|
||||
class="filters-filter"
|
||||
:filter="filter"
|
||||
:available-channels="availableChannels"
|
||||
/>
|
||||
|
||||
<TagFilter
|
||||
class="filters-filter"
|
||||
:filter="filter"
|
||||
:available-tags="availableTags"
|
||||
/>
|
||||
</div>
|
||||
|
@ -44,10 +41,6 @@ import ActorFilter from './actor-filter.vue';
|
|||
import ChannelFilter from './channel-filter.vue';
|
||||
import TagFilter from './tag-filter.vue';
|
||||
|
||||
function filter(state) {
|
||||
return state.ui.filter;
|
||||
}
|
||||
|
||||
function range() {
|
||||
return this.$route.params.range;
|
||||
}
|
||||
|
@ -114,7 +107,6 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
filter,
|
||||
range,
|
||||
batch,
|
||||
}),
|
||||
|
@ -129,6 +121,43 @@ export default {
|
|||
<style lang="scss">
|
||||
@import 'breakpoints';
|
||||
|
||||
.filter {
|
||||
color: var(--shadow);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
|
||||
.filter-applied {
|
||||
flex-grow: 1;
|
||||
padding: .75rem .5rem;
|
||||
font-size: 1rem;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
text-align: right;
|
||||
|
||||
&.empty {
|
||||
color: var(--shadow);
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
fill: var(--shadow);
|
||||
margin: -.1rem 0 0 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
|
||||
.applied {
|
||||
color: var(--shadow-strong);
|
||||
}
|
||||
|
||||
.icon {
|
||||
fill: var(--shadow-strong);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.filter-mode {
|
||||
width: 100%;
|
||||
color: var(--shadow);
|
||||
|
@ -274,43 +303,6 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
::v-deep(.filter) {
|
||||
color: var(--shadow);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
|
||||
.filter-applied {
|
||||
flex-grow: 1;
|
||||
padding: .75rem .5rem;
|
||||
font-size: 1rem;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
text-align: right;
|
||||
|
||||
&.empty {
|
||||
color: var(--shadow);
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
fill: var(--shadow);
|
||||
margin: -.1rem 0 0 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
|
||||
.applied {
|
||||
color: var(--shadow-strong);
|
||||
}
|
||||
|
||||
.icon {
|
||||
fill: var(--shadow-strong);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.filters {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
>Tags</div>
|
||||
</div>
|
||||
|
||||
<template v-slot:tooltip>
|
||||
<template #tooltip>
|
||||
<div
|
||||
class="filter-options"
|
||||
@click.stop
|
||||
|
@ -70,7 +70,7 @@
|
|||
<script>
|
||||
function getNewRange(tag) {
|
||||
if (this.selectedTags.includes(tag)) {
|
||||
return { tags: this.selectedTags.filter(selectedTag => selectedTag !== tag).join(',') || undefined };
|
||||
return { tags: this.selectedTags.filter((selectedTag) => selectedTag !== tag).join(',') || undefined };
|
||||
}
|
||||
|
||||
return { tags: this.selectedTags.concat(tag).join(',') };
|
||||
|
@ -82,10 +82,6 @@ function selectedTags() {
|
|||
|
||||
export default {
|
||||
props: {
|
||||
filter: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
compact: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
|
|
|
@ -28,7 +28,7 @@ export default {
|
|||
};
|
||||
},
|
||||
beforeMount() {
|
||||
this.svg = require(`../../img/icons/${this.icon}.svg`).default;
|
||||
this.svg = require(`../../img/icons/${this.icon}.svg`).default; // eslint-disable-line global-require, import/no-dynamic-require
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -11,16 +11,31 @@
|
|||
class="empty"
|
||||
>No results for "{{ $route.query.query }}"</span>
|
||||
|
||||
<div
|
||||
v-else
|
||||
class="entity-tiles"
|
||||
>
|
||||
<Entity
|
||||
v-for="entity in entities"
|
||||
:key="entity.parent ? `entity-tile-${entity.parent.slug}-${entity.slug}` : `entity-tile-${entity.slug}`"
|
||||
:entity="entity"
|
||||
/>
|
||||
</div>
|
||||
<template v-else>
|
||||
<h2 class="heading">Popular</h2>
|
||||
|
||||
<div
|
||||
class="entity-tiles"
|
||||
>
|
||||
<Entity
|
||||
v-for="entity in popularEntities"
|
||||
:key="entity.parent ? `entity-tile-${entity.parent.slug}-${entity.slug}` : `entity-tile-${entity.slug}`"
|
||||
:entity="entity"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h2 class="heading">All networks</h2>
|
||||
|
||||
<div
|
||||
class="entity-tiles"
|
||||
>
|
||||
<Entity
|
||||
v-for="entity in entities"
|
||||
:key="entity.parent ? `entity-tile-${entity.parent.slug}-${entity.slug}` : `entity-tile-${entity.slug}`"
|
||||
:entity="entity"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<Footer />
|
||||
|
@ -58,6 +73,45 @@ async function searchEntities() {
|
|||
this.done = true;
|
||||
}
|
||||
|
||||
function popularEntities() {
|
||||
const entitiesBySlug = Object.fromEntries(this.entities.map((entity) => [entity.slug, entity]));
|
||||
|
||||
return [
|
||||
'21sextury',
|
||||
'amateurallure',
|
||||
'analvids',
|
||||
'bamvisions',
|
||||
'bang',
|
||||
'bangbros',
|
||||
'blowpass',
|
||||
'brazzers',
|
||||
'burningangel',
|
||||
'digitalplayground',
|
||||
'dogfartnetwork',
|
||||
'dorcel',
|
||||
'elegantangel',
|
||||
'evilangel',
|
||||
'fakehub',
|
||||
'girlsway',
|
||||
'hookuphotshot',
|
||||
'hussiepass',
|
||||
'insex',
|
||||
'julesjordan',
|
||||
'kellymadison',
|
||||
'kink',
|
||||
'mofos',
|
||||
'naughtyamerica',
|
||||
'newsensations',
|
||||
'pervcity',
|
||||
'pornpros',
|
||||
'private',
|
||||
'realitykings',
|
||||
'twistys',
|
||||
'vixen',
|
||||
'xempire',
|
||||
].map((slug) => entitiesBySlug[slug]).filter(Boolean);
|
||||
}
|
||||
|
||||
async function mounted() {
|
||||
this.pageTitle = 'Channels';
|
||||
|
||||
|
@ -82,6 +136,7 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
channelCount,
|
||||
popularEntities,
|
||||
},
|
||||
watch: {
|
||||
$route: fetchEntities,
|
||||
|
@ -130,6 +185,10 @@ export default {
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
.heading {
|
||||
margin: 1rem 0 0 0;
|
||||
}
|
||||
|
||||
@media(max-width: $breakpoint2) {
|
||||
.entity-tiles {
|
||||
grid-gap: .5rem;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div class="media-container">
|
||||
<div
|
||||
class="media"
|
||||
:class="{ center: release.photos.length < 2, preview: !me }"
|
||||
:class="{ center: (release.photos?.length || 0) + (release.scenesPhotos?.length || 0) < 2, preview: !me }"
|
||||
>
|
||||
<div
|
||||
v-if="release.trailer || release.teaser"
|
||||
|
@ -71,24 +71,28 @@
|
|||
</span>
|
||||
</div>
|
||||
|
||||
<template v-if="release.covers && release.covers.length > 0">
|
||||
<a
|
||||
<template v-if="release.covers?.length > 0">
|
||||
<div
|
||||
v-for="cover in release.covers"
|
||||
:key="`cover-${cover.id}`"
|
||||
:href="getPath(cover)"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="item-container"
|
||||
>
|
||||
<img
|
||||
:src="getPath(cover, 'thumbnail')"
|
||||
:style="{ 'background-image': getBgPath(cover, 'lazy') }"
|
||||
:width="cover.thumbnailWidth"
|
||||
:height="cover.thumbnailHeight"
|
||||
class="item cover"
|
||||
loading="lazy"
|
||||
@load="$emit('load', $event)"
|
||||
<a
|
||||
:href="getPath(cover)"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
</a>
|
||||
<img
|
||||
:src="getPath(cover, 'thumbnail')"
|
||||
:style="{ 'background-image': getBgPath(cover, 'lazy') }"
|
||||
:width="cover.thumbnailWidth"
|
||||
:height="cover.thumbnailHeight"
|
||||
class="item cover"
|
||||
loading="lazy"
|
||||
@load="$emit('load', $event)"
|
||||
>
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div
|
||||
|
@ -164,8 +168,8 @@ function poster() {
|
|||
function photos() {
|
||||
const clips = this.release.clips || [];
|
||||
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 photosWithClipPosters = (this.release.photos || []).concat(uniqueClipPosters);
|
||||
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);
|
||||
|
||||
if (this.release.trailer || (this.release.teaser && this.release.teaser.mime !== 'image/gif')) {
|
||||
// poster will be on trailer video
|
||||
|
|
|
@ -14,6 +14,12 @@
|
|||
loading="lazy"
|
||||
>
|
||||
|
||||
<div
|
||||
v-else
|
||||
:title="movie.title"
|
||||
class="unavailable"
|
||||
><Icon icon="blocked" /></div>
|
||||
|
||||
<Icon
|
||||
v-show="(!stash || stash.primary) && favorited"
|
||||
icon="heart7"
|
||||
|
@ -161,7 +167,6 @@ export default {
|
|||
}
|
||||
|
||||
.movie {
|
||||
height: 16rem;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
|
@ -171,18 +176,30 @@ export default {
|
|||
}
|
||||
|
||||
.cover {
|
||||
height: 100%;
|
||||
height: 16rem;
|
||||
width: 11.25rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
box-shadow: 0 0 3px var(--darken-weak);
|
||||
background-color: var(--shadow-hint);
|
||||
|
||||
img {
|
||||
height: 100%;
|
||||
max-width: 12rem;
|
||||
width: 100%;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
}
|
||||
|
||||
.unavailable .icon {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
fill: var(--shadow-hint);
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
|
@ -252,12 +269,12 @@ export default {
|
|||
}
|
||||
|
||||
.stash {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
padding: .25rem .5rem .5rem .25rem;
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
padding: .25rem .5rem .5rem .5rem;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
fill: var(--lighten-weak);
|
||||
filter: drop-shadow(0 0 2px var(--darken));
|
||||
|
||||
|
@ -273,8 +290,9 @@ export default {
|
|||
}
|
||||
|
||||
@media(max-width: $breakpoint-kilo) {
|
||||
.movie {
|
||||
.cover {
|
||||
height: 12rem;
|
||||
width: 8.25rem;
|
||||
}
|
||||
|
||||
/* ensure no half actor names show */
|
||||
|
|
|
@ -21,14 +21,14 @@
|
|||
<Details :release="release" />
|
||||
|
||||
<button
|
||||
v-if="release.photos.length > 0"
|
||||
v-if="release.photos?.length > 0 || release.scenesPhotos?.length > 0"
|
||||
class="album-toggle"
|
||||
@click="$router.push({ hash: '#album' })"
|
||||
><Icon icon="grid3" />View album</button>
|
||||
|
||||
<Album
|
||||
v-if="showAlbum"
|
||||
:items="[release.poster, ...release.photos]"
|
||||
:items="[release.poster, ...(release.photos || []), ...(release.scenesPhotos || [])]"
|
||||
:title="release.title"
|
||||
:path="config.media.mediaPath"
|
||||
@close="$router.replace({ hash: undefined })"
|
||||
|
@ -79,22 +79,23 @@
|
|||
/>
|
||||
|
||||
<div
|
||||
v-if="release.movies && release.movies.length > 0"
|
||||
v-if="release.movies?.length > 0 || release.series?.length > 0"
|
||||
class="row"
|
||||
>
|
||||
<span class="row-label">Part of</span>
|
||||
|
||||
<div class="movies">
|
||||
<router-link
|
||||
v-for="movie in release.movies"
|
||||
v-for="movie in [...release.movies, ...release.series]"
|
||||
:key="`movie-${movie.id}`"
|
||||
:to="{ name: 'movie', params: { releaseId: movie.id, releaseSlug: movie.slug } }"
|
||||
:to="{ name: movie.type || 'movie', params: { releaseId: movie.id, releaseSlug: movie.slug } }"
|
||||
class="movie"
|
||||
>
|
||||
<span class="movie-title">{{ movie.title }}</span>
|
||||
|
||||
<img
|
||||
v-if="movie.covers.length > 0"
|
||||
:src="getPath(movie.covers[0], 'thumbnail')"
|
||||
v-if="movie.covers.length > 0 || movie.poster"
|
||||
:src="getPath(movie.covers[0] || movie.poster, 'thumbnail')"
|
||||
class="movie-cover"
|
||||
>
|
||||
</router-link>
|
||||
|
@ -243,6 +244,10 @@ async function fetchRelease(scroll = true) {
|
|||
this.release = await this.$store.dispatch('fetchMovieById', this.$route.params.releaseId);
|
||||
}
|
||||
|
||||
if (this.$route.name === 'serie') {
|
||||
this.release = await this.$store.dispatch('fetchSerieById', this.$route.params.releaseId);
|
||||
}
|
||||
|
||||
if (scroll && this.$refs.content) {
|
||||
this.$refs.content.scrollTop = 0;
|
||||
}
|
||||
|
@ -278,11 +283,11 @@ function bannerBackground() {
|
|||
function pageTitle() {
|
||||
return this.release
|
||||
&& (this.release.title
|
||||
|| (this.release.actors.length > 0 ? `${this.release.actors.map(actor => actor.name).join(', ')} for ${this.release.entity.name}` : null));
|
||||
|| (this.release.actors.length > 0 ? `${this.release.actors.map((actor) => actor.name).join(', ')} for ${this.release.entity.name}` : null));
|
||||
}
|
||||
|
||||
function showAlbum() {
|
||||
return this.release.photos?.length > 0 && this.$route.hash === '#album';
|
||||
return (this.release.photos?.length > 0 || this.release.scenesPhotos?.length > 0) && this.$route.hash === '#album';
|
||||
}
|
||||
|
||||
export default {
|
||||
|
|
|
@ -299,8 +299,8 @@ export default {
|
|||
}
|
||||
|
||||
.stash {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
|
@ -321,6 +321,7 @@ export default {
|
|||
}
|
||||
|
||||
.row {
|
||||
max-width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
|
|
@ -45,6 +45,8 @@ const tagSlugsByCategory = {
|
|||
'teen',
|
||||
'milf',
|
||||
'blowjob',
|
||||
'gay',
|
||||
'transsexual',
|
||||
'dp',
|
||||
'gangbang',
|
||||
'facial',
|
||||
|
@ -64,6 +66,11 @@ const tagSlugsByCategory = {
|
|||
'tattoos',
|
||||
'piercings',
|
||||
],
|
||||
sexuality: [
|
||||
'gay',
|
||||
'bisexual',
|
||||
'transsexual',
|
||||
],
|
||||
oral: [
|
||||
'blowjob',
|
||||
'pussy-eating',
|
||||
|
@ -80,7 +87,6 @@ const tagSlugsByCategory = {
|
|||
'titty-fucking',
|
||||
'fisting',
|
||||
'anal-fisting',
|
||||
'fisting-dp',
|
||||
],
|
||||
group: [
|
||||
'mfm',
|
||||
|
@ -101,16 +107,6 @@ const tagSlugsByCategory = {
|
|||
'bukkake',
|
||||
'fake-cum',
|
||||
],
|
||||
toys: [
|
||||
'toys',
|
||||
'toy-anal',
|
||||
'toy-dp',
|
||||
'double-dildo',
|
||||
'double-dildo-blowjob',
|
||||
'double-dildo-kiss',
|
||||
'double-dildo-anal',
|
||||
'double-dildo-dp',
|
||||
],
|
||||
roleplay: [
|
||||
'family',
|
||||
'parody',
|
||||
|
@ -119,6 +115,15 @@ const tagSlugsByCategory = {
|
|||
'maid',
|
||||
'nun',
|
||||
],
|
||||
extreme: [
|
||||
'dp',
|
||||
'airtight',
|
||||
'dap',
|
||||
'dvp',
|
||||
'triple-penetration',
|
||||
'tap',
|
||||
'tvp',
|
||||
],
|
||||
fetish: [
|
||||
'bdsm',
|
||||
'femdom',
|
||||
|
@ -127,15 +132,15 @@ const tagSlugsByCategory = {
|
|||
'latex',
|
||||
'blindfold',
|
||||
],
|
||||
extreme: [
|
||||
'dp',
|
||||
'airtight',
|
||||
'dap',
|
||||
'dvp',
|
||||
'da-tp',
|
||||
'dv-tp',
|
||||
'tap',
|
||||
'tvp',
|
||||
toys: [
|
||||
'toys',
|
||||
'toy-anal',
|
||||
'toy-dp',
|
||||
'double-dildo',
|
||||
'double-dildo-blowjob',
|
||||
'double-dildo-kiss',
|
||||
'double-dildo-anal',
|
||||
'double-dildo-dp',
|
||||
],
|
||||
misc: [
|
||||
'gaping',
|
||||
|
@ -162,10 +167,18 @@ async function fetchTags() {
|
|||
|
||||
const tagsBySlug = tags.reduce((acc, tag) => ({ ...acc, [tag.slug]: tag }), {});
|
||||
|
||||
this.categories = Object.entries(tagSlugsByCategory).reduce((acc, [category, tagSlugs]) => ({
|
||||
...acc,
|
||||
[category]: tagSlugs.map(tagSlug => tagsBySlug[tagSlug]),
|
||||
}), {});
|
||||
this.categories = Object.entries(tagSlugsByCategory).reduce((acc, [category, tagSlugs]) => {
|
||||
const categoryTags = tagSlugs.map((tagSlug) => tagsBySlug[tagSlug]).filter(Boolean);
|
||||
|
||||
if (categoryTags.length === 0) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
return {
|
||||
...acc,
|
||||
[category]: categoryTags,
|
||||
};
|
||||
}, {});
|
||||
}
|
||||
|
||||
async function searchTags() {
|
||||
|
@ -202,6 +215,7 @@ export default {
|
|||
},
|
||||
watch: {
|
||||
$route: fetchTags,
|
||||
'$store.state.ui.tagFilter': fetchTags,
|
||||
},
|
||||
mounted,
|
||||
methods: {
|
||||
|
|
|
@ -44,6 +44,11 @@
|
|||
&:hover {
|
||||
background: var(--primary-strong);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background: var(--shadow-weak);
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
.button-secondary {
|
||||
|
|
|
@ -5,7 +5,7 @@ $breakpoint3: 1200px;
|
|||
$breakpoint4: 1500px;
|
||||
|
||||
:root {
|
||||
--primary: #e33379;
|
||||
--primary: #f65596;
|
||||
--primary-strong: #f90071;
|
||||
--primary-faded: #ffcce4;
|
||||
|
||||
|
|
|
@ -65,19 +65,23 @@ function curateActor(actor, release) {
|
|||
return curatedActor;
|
||||
}
|
||||
|
||||
function curateRelease(release) {
|
||||
function curateRelease(release, type = 'scene') {
|
||||
const curatedRelease = {
|
||||
...release,
|
||||
type: release.type || type,
|
||||
actors: [],
|
||||
poster: release.poster && release.poster.media,
|
||||
tags: release.tags ? release.tags.map((tag) => tag.tag || tag) : [],
|
||||
};
|
||||
|
||||
if (release.scenes) curatedRelease.scenes = release.scenes.filter(Boolean).map(({ scene }) => curateRelease(scene));
|
||||
if (release.movies) curatedRelease.movies = release.movies.filter(Boolean).map(({ movie }) => curateRelease(movie));
|
||||
if (release.chapters) curatedRelease.chapters = release.chapters.filter(Boolean).map((chapter) => curateRelease(chapter));
|
||||
if (release.photos) curatedRelease.photos = release.photos.filter(Boolean).map((photo) => photo.media || photo);
|
||||
if (release.covers) curatedRelease.covers = release.covers.filter(Boolean).map(({ media }) => media);
|
||||
curatedRelease.scenes = release.scenes?.filter(Boolean).map(({ scene }) => curateRelease(scene, 'scene')) || [];
|
||||
curatedRelease.movies = release.movies?.filter(Boolean).map(({ movie }) => curateRelease(movie, 'movie')) || [];
|
||||
curatedRelease.series = release.series?.filter(Boolean).map(({ serie }) => curateRelease(serie, 'serie')) || [];
|
||||
curatedRelease.chapters = release.chapters?.filter(Boolean).map((chapter) => curateRelease(chapter)) || [];
|
||||
curatedRelease.photos = release.photos?.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) || [];
|
||||
|
||||
if (release.trailer) curatedRelease.trailer = release.trailer.media;
|
||||
if (release.teaser) curatedRelease.teaser = release.teaser.media;
|
||||
if (release.actors) curatedRelease.actors = release.actors.filter(Boolean).map((actor) => curateActor(actor.actor || actor, curatedRelease));
|
||||
|
@ -105,6 +109,7 @@ function curateEntity(entity, parent, releases) {
|
|||
};
|
||||
|
||||
if (entity.tags) curatedEntity.tags = entity.tags.map(({ tag }) => tag);
|
||||
if (entity.sceneTags) curatedEntity.sceneTags = entity.sceneTags;
|
||||
|
||||
if (entity.children) {
|
||||
if (entity.children.nodes) {
|
||||
|
@ -117,9 +122,7 @@ function curateEntity(entity, parent, releases) {
|
|||
if (entity.parent || parent) curatedEntity.parent = curateEntity(entity.parent || parent);
|
||||
if (releases) curatedEntity.releases = releases.map((release) => curateRelease(release));
|
||||
|
||||
if (entity.connection) {
|
||||
curatedEntity.sceneTotal = entity.connection.totalCount;
|
||||
}
|
||||
curatedEntity.sceneTotal = entity.sceneTotal;
|
||||
|
||||
return curatedEntity;
|
||||
}
|
||||
|
|
|
@ -22,8 +22,6 @@ function initEntitiesActions(store, router) {
|
|||
$offset: Int = 0,
|
||||
$after: Datetime = "1900-01-01",
|
||||
$before: Datetime = "2100-01-01",
|
||||
$afterTime: Datetime = "1900-01-01",
|
||||
$beforeTime: Datetime = "2100-01-01",
|
||||
$orderBy: [ReleasesOrderBy!]
|
||||
$exclude: [String!]
|
||||
$hasAuth: Boolean!
|
||||
|
@ -43,6 +41,11 @@ function initEntitiesActions(store, router) {
|
|||
slug
|
||||
}
|
||||
}
|
||||
sceneTags {
|
||||
id
|
||||
name
|
||||
slug
|
||||
}
|
||||
children: childEntitiesConnection(
|
||||
orderBy: [PRIORITY_DESC, NAME_ASC],
|
||||
filter: {
|
||||
|
@ -64,12 +67,10 @@ function initEntitiesActions(store, router) {
|
|||
independent
|
||||
hasLogo
|
||||
${campaignsFragment}
|
||||
sceneTotal
|
||||
children: childEntitiesConnection {
|
||||
totalCount
|
||||
}
|
||||
connection: scenesConnection {
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
}
|
||||
${campaignsFragment}
|
||||
|
@ -91,20 +92,19 @@ function initEntitiesActions(store, router) {
|
|||
or: [
|
||||
{
|
||||
date: {
|
||||
lessThan: $before,
|
||||
greaterThan: $after
|
||||
isNull: ${entityType !== 'network'}
|
||||
}
|
||||
},
|
||||
}
|
||||
{
|
||||
date: {
|
||||
isNull: true
|
||||
},
|
||||
createdAt: {
|
||||
lessThan: $beforeTime,
|
||||
greaterThan: $afterTime,
|
||||
isNull: false
|
||||
}
|
||||
}
|
||||
]
|
||||
effectiveDate: {
|
||||
lessThan: $before,
|
||||
greaterThan: $after
|
||||
}
|
||||
releasesTagsConnection: {
|
||||
none: {
|
||||
tag: {
|
||||
|
@ -131,8 +131,6 @@ function initEntitiesActions(store, router) {
|
|||
after,
|
||||
before,
|
||||
orderBy,
|
||||
afterTime: store.getters.after,
|
||||
beforeTime: store.getters.before,
|
||||
exclude: store.state.ui.tagFilter,
|
||||
hasAuth: !!store.state.auth.user,
|
||||
userId: store.state.auth.user?.id,
|
||||
|
@ -202,9 +200,6 @@ function initEntitiesActions(store, router) {
|
|||
children: childEntitiesConnection {
|
||||
totalCount
|
||||
}
|
||||
connection: scenesConnection {
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
}
|
||||
`, {
|
||||
|
|
|
@ -125,7 +125,7 @@ const movieFields = `
|
|||
type
|
||||
}
|
||||
}
|
||||
covers: moviesCovers {
|
||||
covers: moviesCovers(orderBy: MEDIA_BY_MEDIA_ID__INDEX_ASC) {
|
||||
media {
|
||||
id
|
||||
path
|
||||
|
@ -442,6 +442,29 @@ const releasesFragment = `
|
|||
}
|
||||
`;
|
||||
|
||||
const mediaFields = `
|
||||
id
|
||||
index
|
||||
path
|
||||
thumbnail
|
||||
lazy
|
||||
isS3
|
||||
comment
|
||||
sfw: sfwMedia {
|
||||
id
|
||||
thumbnail
|
||||
lazy
|
||||
path
|
||||
comment
|
||||
}
|
||||
`;
|
||||
|
||||
const mediaFragment = `
|
||||
media {
|
||||
${mediaFields}
|
||||
}
|
||||
`;
|
||||
|
||||
const releaseFragment = `
|
||||
release(id: $releaseId) {
|
||||
id
|
||||
|
@ -516,7 +539,7 @@ const releaseFragment = `
|
|||
id
|
||||
title
|
||||
slug
|
||||
covers: moviesCovers {
|
||||
covers: moviesCovers(orderBy: MEDIA_BY_MEDIA_ID__INDEX_ASC) {
|
||||
media {
|
||||
id
|
||||
index
|
||||
|
@ -536,6 +559,19 @@ const releaseFragment = `
|
|||
}
|
||||
}
|
||||
}
|
||||
series: seriesScenesBySceneId {
|
||||
serie {
|
||||
id
|
||||
title
|
||||
slug
|
||||
covers: seriesCoversBySerieId(orderBy: MEDIA_BY_MEDIA_ID__INDEX_ASC) {
|
||||
${mediaFragment}
|
||||
}
|
||||
poster: seriesPosterBySerieId {
|
||||
${mediaFragment}
|
||||
}
|
||||
}
|
||||
}
|
||||
isFavorited
|
||||
isStashed(includeFavorites: false)
|
||||
stashes: stashesScenesBySceneId(
|
||||
|
@ -624,6 +660,8 @@ export {
|
|||
actorFields,
|
||||
actorStashesFields,
|
||||
campaignsFragment,
|
||||
mediaFields,
|
||||
mediaFragment,
|
||||
movieFields,
|
||||
releaseActorsFragment,
|
||||
releaseFields,
|
||||
|
|
|
@ -3,30 +3,6 @@ import dayjs from 'dayjs';
|
|||
|
||||
dayjs.extend(utc);
|
||||
|
||||
const dateRanges = {
|
||||
latest: () => ({
|
||||
after: '1900-01-01',
|
||||
before: dayjs.utc().toDate(),
|
||||
orderBy: ['DATE_DESC', 'CREATED_AT_DESC'],
|
||||
}),
|
||||
upcoming: () => ({
|
||||
after: dayjs.utc().toDate(),
|
||||
before: '2100-01-01',
|
||||
orderBy: ['DATE_ASC', 'CREATED_AT_ASC'],
|
||||
}),
|
||||
new: () => ({
|
||||
after: '1900-01-01 00:00:00',
|
||||
before: '2100-01-01',
|
||||
orderBy: ['CREATED_AT_DESC', 'DATE_ASC'],
|
||||
}),
|
||||
all: () => ({
|
||||
after: '1900-01-01',
|
||||
before: '2100-01-01',
|
||||
orderBy: ['DATE_DESC', 'CREATED_AT_DESC'],
|
||||
}),
|
||||
};
|
||||
|
||||
/* requires PostgreSQL 12.x> not available in production yet
|
||||
const dateRanges = {
|
||||
latest: () => ({
|
||||
after: '1900-01-01',
|
||||
|
@ -49,7 +25,6 @@ const dateRanges = {
|
|||
orderBy: ['EFFECTIVE_DATE_DESC'],
|
||||
}),
|
||||
};
|
||||
*/
|
||||
|
||||
function getDateRange(range) {
|
||||
return (dateRanges[range] || dateRanges.all)();
|
||||
|
|
|
@ -4,6 +4,8 @@ import {
|
|||
releaseFragment,
|
||||
releaseFields,
|
||||
movieFields,
|
||||
mediaFragment,
|
||||
mediaFields,
|
||||
} from '../fragments';
|
||||
import { curateRelease } from '../curate';
|
||||
import getDateRange from '../get-date-range';
|
||||
|
@ -110,6 +112,8 @@ function initReleasesActions(store, router) {
|
|||
$query: String!
|
||||
$limit:Int = 20
|
||||
$offset:Int = 0
|
||||
$hasAuth: Boolean!
|
||||
$userId: Int
|
||||
) {
|
||||
connection: searchMoviesConnection(
|
||||
query: $query
|
||||
|
@ -126,6 +130,8 @@ function initReleasesActions(store, router) {
|
|||
}
|
||||
}
|
||||
`, {
|
||||
hasAuth: !!store.state.auth.user,
|
||||
userId: store.state.auth.user?.id,
|
||||
query,
|
||||
limit,
|
||||
offset: Math.max(0, (pageNumber - 1)) * limit,
|
||||
|
@ -137,16 +143,16 @@ function initReleasesActions(store, router) {
|
|||
};
|
||||
}
|
||||
|
||||
async function fetchMovieById({ _commit }, movieId) {
|
||||
async function fetchCollectionById({ _commit }, movieId, type = 'movie') {
|
||||
// const release = await get(`/releases/${releaseId}`);
|
||||
|
||||
const { movie } = await graphql(`
|
||||
const result = await graphql(`
|
||||
query Movie(
|
||||
$movieId: Int!
|
||||
$hasAuth: Boolean!
|
||||
$userId: Int
|
||||
) {
|
||||
movie(id: $movieId) {
|
||||
${type}(id: $movieId) {
|
||||
id
|
||||
title
|
||||
description
|
||||
|
@ -178,7 +184,7 @@ function initReleasesActions(store, router) {
|
|||
isS3
|
||||
}
|
||||
}
|
||||
poster: moviesPosterByMovieId {
|
||||
poster: ${type === 'series' ? 'seriesPosterBySerieId' : 'moviesPoster'} {
|
||||
media {
|
||||
id
|
||||
path
|
||||
|
@ -191,7 +197,7 @@ function initReleasesActions(store, router) {
|
|||
isS3
|
||||
}
|
||||
}
|
||||
covers: moviesCovers {
|
||||
covers: ${type === 'series' ? 'seriesCoversBySerieId' : 'moviesCovers'}(orderBy: MEDIA_BY_MEDIA_ID__INDEX_ASC) {
|
||||
media {
|
||||
id
|
||||
path
|
||||
|
@ -204,14 +210,14 @@ function initReleasesActions(store, router) {
|
|||
isS3
|
||||
}
|
||||
}
|
||||
trailer: moviesTrailerByMovieId {
|
||||
trailer: ${type === 'series' ? 'seriesTrailerBySerieId' : 'moviesTrailer'} {
|
||||
media {
|
||||
id
|
||||
path
|
||||
isS3
|
||||
}
|
||||
}
|
||||
scenes: moviesScenes {
|
||||
scenes: ${type === 'series' ? 'seriesScenesBySerieId' : 'moviesScenes'} {
|
||||
scene {
|
||||
${releaseFields}
|
||||
}
|
||||
|
@ -221,25 +227,11 @@ function initReleasesActions(store, router) {
|
|||
slug
|
||||
name
|
||||
}
|
||||
photos {
|
||||
id
|
||||
index
|
||||
path
|
||||
thumbnail
|
||||
lazy
|
||||
width
|
||||
height
|
||||
thumbnailWidth
|
||||
thumbnailHeight
|
||||
isS3
|
||||
comment
|
||||
sfw: sfwMedia {
|
||||
id
|
||||
thumbnail
|
||||
lazy
|
||||
path
|
||||
comment
|
||||
}
|
||||
photos: ${type === 'series' ? 'seriesPhotosBySerieId' : 'moviesPhotos'} {
|
||||
${mediaFragment}
|
||||
}
|
||||
scenesPhotos {
|
||||
${mediaFields}
|
||||
}
|
||||
entity {
|
||||
id
|
||||
|
@ -255,7 +247,7 @@ function initReleasesActions(store, router) {
|
|||
hasLogo
|
||||
}
|
||||
}
|
||||
stashes: stashesMovies(
|
||||
stashes: ${type === 'series' ? 'stashesSeriesBySerieId' : 'stashesMovies'}(
|
||||
filter: {
|
||||
stash: {
|
||||
userId: {
|
||||
|
@ -279,12 +271,20 @@ function initReleasesActions(store, router) {
|
|||
userId: store.state.auth.user?.id,
|
||||
});
|
||||
|
||||
if (!movie) {
|
||||
if (!result[type]) {
|
||||
router.replace('/not-found');
|
||||
return null;
|
||||
}
|
||||
|
||||
return curateRelease(movie);
|
||||
return curateRelease(result[type]);
|
||||
}
|
||||
|
||||
async function fetchMovieById(context, movieId) {
|
||||
return fetchCollectionById(context, movieId, 'movie');
|
||||
}
|
||||
|
||||
async function fetchSerieById(context, serieId) {
|
||||
return fetchCollectionById(context, serieId, 'series');
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -292,6 +292,7 @@ function initReleasesActions(store, router) {
|
|||
fetchReleaseById,
|
||||
fetchMovies,
|
||||
fetchMovieById,
|
||||
fetchSerieById,
|
||||
searchMovies,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -71,6 +71,11 @@ const routes = [
|
|||
component: Release,
|
||||
name: 'movie',
|
||||
},
|
||||
{
|
||||
path: '/serie/:releaseId/:releaseSlug?',
|
||||
component: Release,
|
||||
name: 'serie',
|
||||
},
|
||||
{
|
||||
path: '/actor/:actorId/:actorSlug',
|
||||
name: 'actor',
|
||||
|
|
|
@ -210,9 +210,15 @@ function initTagsActions(store, _router) {
|
|||
query Tags(
|
||||
$slugs: [String!] = [],
|
||||
$limit: Int = 100
|
||||
$exclude: [String!]
|
||||
) {
|
||||
tags(
|
||||
filter: { slug: { in: $slugs } },
|
||||
filter: {
|
||||
slug: {
|
||||
in: $slugs
|
||||
notIn: $exclude
|
||||
}
|
||||
},
|
||||
first: $limit
|
||||
) {
|
||||
id
|
||||
|
@ -257,6 +263,7 @@ function initTagsActions(store, _router) {
|
|||
`, {
|
||||
slugs,
|
||||
limit,
|
||||
exclude: store.state.ui.tagFilter,
|
||||
});
|
||||
|
||||
return tags.map((tag) => curateTag(tag, store.state.ui.sfw));
|
||||
|
@ -283,7 +290,7 @@ function initTagsActions(store, _router) {
|
|||
id
|
||||
name
|
||||
slug
|
||||
poster: tagsPosterByTagId {
|
||||
poster: tagsPoster {
|
||||
media {
|
||||
thumbnail
|
||||
comment
|
||||
|
|
|
@ -90,7 +90,7 @@ function initUsersActions(store, _router) {
|
|||
${actorFields}
|
||||
}
|
||||
}
|
||||
entity: alertsEntityByAlertId {
|
||||
entity: alertsEntity {
|
||||
entity {
|
||||
id
|
||||
name
|
||||
|
|
|
@ -66,10 +66,7 @@ module.exports = {
|
|||
// pornpros
|
||||
'milfhumiliation',
|
||||
'humiliated',
|
||||
'flexiblepositions',
|
||||
'publicviolations',
|
||||
'amateurviolations',
|
||||
'squirtdisgrace',
|
||||
'cumdisgrace',
|
||||
'webcamhackers',
|
||||
'collegeteens',
|
||||
|
@ -301,10 +298,6 @@ module.exports = {
|
|||
interval: 1000,
|
||||
concurrency: 1,
|
||||
},
|
||||
'www.realitykings.com': {
|
||||
interval: 1000,
|
||||
concurrency: 1,
|
||||
},
|
||||
'westcoastproductions.com': {
|
||||
interval: 100,
|
||||
concurrency: 1,
|
||||
|
@ -316,8 +309,15 @@ module.exports = {
|
|||
},
|
||||
fetchAfter: [1, 'week'],
|
||||
missingDateLimit: 3,
|
||||
memorySampling: {
|
||||
enabled: false,
|
||||
sampleDuration: 300000, // 5 minutes
|
||||
snapshotIntervals: [],
|
||||
},
|
||||
media: {
|
||||
path: './media',
|
||||
maxSize: 1000,
|
||||
quality: 80,
|
||||
thumbnailSize: 320, // width for 16:9 will be exactly 576px
|
||||
thumbnailQuality: 100,
|
||||
lazySize: 90,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const config = require('config');
|
||||
|
||||
exports.up = knex => Promise.resolve()
|
||||
exports.up = (knex) => Promise.resolve()
|
||||
.then(() => knex.schema.createTable('countries', (table) => {
|
||||
table.text('alpha2', 2)
|
||||
.unique()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
exports.up = async knex => knex.raw(`
|
||||
exports.up = async (knex) => knex.raw(`
|
||||
CREATE FUNCTION entities_scenes(entity entities) RETURNS SETOF releases AS $$
|
||||
WITH RECURSIVE children AS (
|
||||
SELECT entities.id
|
||||
|
@ -13,12 +13,17 @@ exports.up = async knex => knex.raw(`
|
|||
)
|
||||
|
||||
SELECT releases FROM releases
|
||||
INNER JOIN children ON children.id = releases.entity_id;
|
||||
INNER JOIN children ON children.id = releases.entity_id
|
||||
|
||||
UNION
|
||||
|
||||
SELECT releases FROM releases
|
||||
INNER JOIN children ON children.id = releases.studio_id;
|
||||
$$ LANGUAGE SQL STABLE;
|
||||
|
||||
COMMENT ON FUNCTION entities_scenes IS E'@sortable';
|
||||
`);
|
||||
|
||||
exports.down = async knex => knex.raw(`
|
||||
exports.down = async (knex) => knex.raw(`
|
||||
DROP FUNCTION IF EXISTS entities_scenes;
|
||||
`);
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
exports.up = async (knex) => Promise.resolve()
|
||||
.then(() => knex.schema.alterTable('releases_tags', (table) => {
|
||||
table.index('release_id');
|
||||
}))
|
||||
.then(() => knex.schema.alterTable('movies_scenes', (table) => {
|
||||
table.index('scene_id');
|
||||
}));
|
||||
|
||||
exports.down = async (knex) => Promise.resolve()
|
||||
.then(() => knex.schema.alterTable('releases_tags', (table) => {
|
||||
table.dropIndex('release_id');
|
||||
}))
|
||||
.then(() => knex.schema.alterTable('movies_scenes', (table) => {
|
||||
table.dropIndex('scene_id');
|
||||
}));
|
|
@ -0,0 +1,11 @@
|
|||
exports.up = async (knex) => knex.raw(`
|
||||
CREATE OR REPLACE FUNCTION entities_scene_total(entity entities) RETURNS bigint AS $$
|
||||
SELECT COUNT(id)
|
||||
FROM releases
|
||||
WHERE releases.entity_id = entity.id;
|
||||
$$ LANGUAGE SQL STABLE;
|
||||
`);
|
||||
|
||||
exports.down = async (knex) => knex.raw(`
|
||||
DROP FUNCTION IF EXISTS entities_scene_total;
|
||||
`);
|
|
@ -0,0 +1,23 @@
|
|||
exports.up = async (knex) => knex.raw(`
|
||||
CREATE FUNCTION entities_scene_tags(entity entities, selectable_tags text[]) RETURNS SETOF tags AS $$
|
||||
SELECT tags.*
|
||||
FROM releases
|
||||
LEFT JOIN
|
||||
releases_tags ON releases_tags.release_id = releases.id
|
||||
LEFT JOIN
|
||||
tags ON tags.id = releases_tags.tag_id
|
||||
WHERE
|
||||
releases.entity_id = entity.id
|
||||
AND
|
||||
CASE WHEN array_length(selectable_tags, 1) IS NOT NULL
|
||||
THEN tags.slug = ANY(selectable_tags)
|
||||
ELSE true
|
||||
END
|
||||
GROUP BY tags.id
|
||||
ORDER BY tags.name;
|
||||
$$ LANGUAGE SQL STABLE;
|
||||
`);
|
||||
|
||||
exports.down = async (knex) => knex.raw(`
|
||||
DROP FUNCTION IF EXISTS entities_scene_tags;
|
||||
`);
|
|
@ -0,0 +1,215 @@
|
|||
const config = require('config');
|
||||
|
||||
exports.up = async (knex) => Promise.resolve()
|
||||
.then(() => knex.schema.createTable('series', (table) => {
|
||||
table.increments('id', 16);
|
||||
|
||||
table.integer('entity_id', 12)
|
||||
.references('id')
|
||||
.inTable('entities')
|
||||
.notNullable();
|
||||
|
||||
table.integer('studio_id', 12)
|
||||
.references('id')
|
||||
.inTable('entities');
|
||||
|
||||
table.text('entry_id');
|
||||
table.unique(['entity_id', 'entry_id']);
|
||||
|
||||
table.text('url', 1000);
|
||||
table.text('title');
|
||||
table.text('slug');
|
||||
|
||||
table.timestamp('date');
|
||||
table.index('date');
|
||||
|
||||
table.enum('date_precision', ['year', 'month', 'week', 'day', 'hour', 'minute', 'second'])
|
||||
.defaultTo('day');
|
||||
|
||||
table.text('description');
|
||||
|
||||
table.boolean('deep');
|
||||
table.text('deep_url', 1000);
|
||||
|
||||
table.text('comment');
|
||||
|
||||
table.integer('created_batch_id', 12)
|
||||
.references('id')
|
||||
.inTable('batches')
|
||||
.onDelete('cascade');
|
||||
|
||||
table.integer('updated_batch_id', 12)
|
||||
.references('id')
|
||||
.inTable('batches')
|
||||
.onDelete('cascade');
|
||||
|
||||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('series_scenes', (table) => {
|
||||
table.integer('serie_id', 16)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('series')
|
||||
.onDelete('cascade');
|
||||
|
||||
table.integer('scene_id', 16)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('releases')
|
||||
.onDelete('cascade');
|
||||
|
||||
table.unique(['serie_id', 'scene_id']);
|
||||
|
||||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('series_trailers', (table) => {
|
||||
table.integer('serie_id', 16)
|
||||
.unique()
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('series')
|
||||
.onDelete('cascade');
|
||||
|
||||
table.text('media_id', 21)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('media');
|
||||
}))
|
||||
.then(() => knex.schema.createTable('series_posters', (table) => {
|
||||
table.integer('serie_id', 16)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('series')
|
||||
.onDelete('cascade');
|
||||
|
||||
table.text('media_id', 21)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('media')
|
||||
.onDelete('cascade');
|
||||
|
||||
table.unique('serie_id');
|
||||
}))
|
||||
.then(() => knex.schema.createTable('series_covers', (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', 'media_id']);
|
||||
}))
|
||||
.then(() => knex.schema.createTable('series_search', (table) => {
|
||||
table.integer('serie_id', 16)
|
||||
.references('id')
|
||||
.inTable('series')
|
||||
.onDelete('cascade');
|
||||
}))
|
||||
.then(() => knex.schema.createTable('stashes_series', (table) => {
|
||||
table.integer('stash_id')
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('stashes')
|
||||
.onDelete('cascade');
|
||||
|
||||
table.integer('serie_id')
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('series')
|
||||
.onDelete('cascade');
|
||||
|
||||
table.unique(['stash_id', 'serie_id']);
|
||||
|
||||
table.string('comment');
|
||||
|
||||
table.datetime('created_at')
|
||||
.notNullable()
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.raw(`
|
||||
ALTER TABLE series_search ADD COLUMN document tsvector;
|
||||
|
||||
CREATE UNIQUE INDEX series_search_unique ON series_search (serie_id);
|
||||
CREATE INDEX series_search_index ON series_search USING GIN (document);
|
||||
|
||||
CREATE FUNCTION series_actors(serie series) RETURNS SETOF actors AS $$
|
||||
SELECT actors.*
|
||||
FROM series_scenes
|
||||
LEFT JOIN
|
||||
releases ON releases.id = series_scenes.scene_id
|
||||
LEFT JOIN
|
||||
releases_actors ON releases_actors.release_id = releases.id
|
||||
LEFT JOIN
|
||||
actors ON actors.id = releases_actors.actor_id
|
||||
WHERE series_scenes.serie_id = serie.id
|
||||
AND actors.id IS NOT NULL
|
||||
GROUP BY actors.id
|
||||
ORDER BY actors.name, actors.gender
|
||||
$$ LANGUAGE SQL STABLE;
|
||||
|
||||
CREATE FUNCTION series_tags(serie series) RETURNS SETOF tags AS $$
|
||||
SELECT tags.*
|
||||
FROM series_scenes
|
||||
LEFT JOIN
|
||||
releases ON releases.id = series_scenes.scene_id
|
||||
LEFT JOIN
|
||||
releases_tags ON releases_tags.release_id = releases.id
|
||||
LEFT JOIN
|
||||
tags ON tags.id = releases_tags.tag_id
|
||||
WHERE series_scenes.serie_id = serie.id
|
||||
AND tags.id IS NOT NULL
|
||||
GROUP BY tags.id
|
||||
ORDER BY tags.priority DESC
|
||||
$$ LANGUAGE SQL STABLE;
|
||||
|
||||
CREATE FUNCTION series_photos(serie series) RETURNS SETOF media AS $$
|
||||
SELECT media.*
|
||||
FROM series_scenes
|
||||
LEFT JOIN
|
||||
releases ON releases.id = series_scenes.scene_id
|
||||
INNER JOIN
|
||||
releases_photos ON releases_photos.release_id = releases.id
|
||||
LEFT JOIN
|
||||
media ON media.id = releases_photos.media_id
|
||||
WHERE series_scenes.serie_id = serie.id
|
||||
GROUP BY media.id
|
||||
ORDER BY media.index ASC
|
||||
$$ LANGUAGE SQL STABLE;
|
||||
|
||||
GRANT ALL ON ALL TABLES IN SCHEMA public TO :visitor;
|
||||
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO :visitor;
|
||||
|
||||
ALTER TABLE stashes_series ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
CREATE POLICY stashes_policy ON stashes_series
|
||||
USING (EXISTS (
|
||||
SELECT *
|
||||
FROM stashes
|
||||
WHERE stashes.id = stashes_series.stash_id
|
||||
AND (stashes.user_id = current_user_id() OR stashes.public)
|
||||
));
|
||||
`, {
|
||||
visitor: knex.raw(config.database.query.user),
|
||||
}));
|
||||
|
||||
exports.down = async (knex) => Promise.resolve()
|
||||
.then(() => knex.raw(`
|
||||
DROP FUNCTION IF EXISTS series_actors;
|
||||
DROP FUNCTION IF EXISTS series_tags;
|
||||
DROP FUNCTION IF EXISTS series_photos;
|
||||
|
||||
DROP TABLE IF EXISTS stashes_series CASCADE;
|
||||
DROP TABLE IF EXISTS series_scenes CASCADE;
|
||||
DROP TABLE IF EXISTS series_trailers CASCADE;
|
||||
DROP TABLE IF EXISTS series_posters CASCADE;
|
||||
DROP TABLE IF EXISTS series_covers CASCADE;
|
||||
DROP TABLE IF EXISTS series_search CASCADE;
|
||||
DROP TABLE IF EXISTS series CASCADE;
|
||||
`));
|
|
@ -0,0 +1,49 @@
|
|||
const config = require('config');
|
||||
|
||||
exports.up = async (knex) => Promise.resolve()
|
||||
.then(() => knex.raw(`
|
||||
ALTER FUNCTION movies_photos(movie movies) RENAME TO movies_scenes_photos;
|
||||
ALTER FUNCTION series_photos(serie series) RENAME TO series_scenes_photos;
|
||||
`))
|
||||
.then(() => knex.schema.createTable('movies_photos', (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', 'media_id']);
|
||||
}))
|
||||
.then(() => knex.schema.createTable('series_photos', (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', 'media_id']);
|
||||
}))
|
||||
.then(() => knex.raw(`
|
||||
GRANT ALL ON ALL TABLES IN SCHEMA public TO :visitor;
|
||||
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO :visitor;
|
||||
`, {
|
||||
visitor: knex.raw(config.database.query.user),
|
||||
}));
|
||||
|
||||
exports.down = async (knex) => knex.raw(`
|
||||
DROP TABLE IF EXISTS movies_photos CASCADE;
|
||||
DROP TABLE IF EXISTS series_photos CASCADE;
|
||||
|
||||
ALTER FUNCTION movies_scenes_photos(movie movies) RENAME TO movies_photos;
|
||||
ALTER FUNCTION series_scenes_photos(serie series) RENAME TO series_photos;
|
||||
`);
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "traxxx",
|
||||
"version": "1.200.2",
|
||||
"version": "1.212.9",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "traxxx",
|
||||
"version": "1.200.2",
|
||||
"version": "1.212.9",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@casl/ability": "^5.2.2",
|
||||
|
@ -57,6 +57,7 @@
|
|||
"mitt": "^3.0.0",
|
||||
"moment": "^2.24.0",
|
||||
"nanoid": "^3.1.30",
|
||||
"node-fetch": "^2.6.7",
|
||||
"object-merge-advanced": "^12.1.0",
|
||||
"object.omit": "^3.0.0",
|
||||
"opn": "^6.0.0",
|
||||
|
@ -72,6 +73,7 @@
|
|||
"tippy.js": "^6.3.1",
|
||||
"tough-cookie": "^4.0.0",
|
||||
"tunnel": "0.0.6",
|
||||
"undici": "^4.13.0",
|
||||
"url-pattern": "^1.0.3",
|
||||
"v-tooltip": "^2.0.3",
|
||||
"video.js": "^7.11.4",
|
||||
|
@ -11611,14 +11613,41 @@
|
|||
"integrity": "sha512-eazsqzwG2lskuzBqCGPi7Ac2UgOoMz8JVOXVhTvvPDYhthvNpefx8jWD8Np7Gv+2Sz0FlPWZk0nJV0z598Wn8Q=="
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.6.5",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz",
|
||||
"integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==",
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||
"dependencies": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "4.x || >=6.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"encoding": "^0.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"encoding": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch/node_modules/tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
|
||||
},
|
||||
"node_modules/node-fetch/node_modules/webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
|
||||
},
|
||||
"node_modules/node-fetch/node_modules/whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
|
||||
"dependencies": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch/node_modules/tr46": {
|
||||
|
@ -16346,6 +16375,14 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "4.13.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-4.13.0.tgz",
|
||||
"integrity": "sha512-8lk8S/f2V0VUNGf2scU2b+KI2JSzEQLdCyRNRF3XmHu+5jectlSDaPSBCXAHFaUlt1rzngzOBVDgJS9/Gue/KA==",
|
||||
"engines": {
|
||||
"node": ">=12.18"
|
||||
}
|
||||
},
|
||||
"node_modules/unicode-canonical-property-names-ecmascript": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
|
||||
|
@ -26407,9 +26444,9 @@
|
|||
"integrity": "sha512-eazsqzwG2lskuzBqCGPi7Ac2UgOoMz8JVOXVhTvvPDYhthvNpefx8jWD8Np7Gv+2Sz0FlPWZk0nJV0z598Wn8Q=="
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.5",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz",
|
||||
"integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==",
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||
"requires": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
|
@ -30068,6 +30105,11 @@
|
|||
"resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
|
||||
"integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo="
|
||||
},
|
||||
"undici": {
|
||||
"version": "4.13.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-4.13.0.tgz",
|
||||
"integrity": "sha512-8lk8S/f2V0VUNGf2scU2b+KI2JSzEQLdCyRNRF3XmHu+5jectlSDaPSBCXAHFaUlt1rzngzOBVDgJS9/Gue/KA=="
|
||||
},
|
||||
"unicode-canonical-property-names-ecmascript": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "traxxx",
|
||||
"version": "1.200.2",
|
||||
"version": "1.212.9",
|
||||
"description": "All the latest porn releases in one place",
|
||||
"main": "src/app.js",
|
||||
"scripts": {
|
||||
|
@ -116,6 +116,7 @@
|
|||
"mitt": "^3.0.0",
|
||||
"moment": "^2.24.0",
|
||||
"nanoid": "^3.1.30",
|
||||
"node-fetch": "^2.6.7",
|
||||
"object-merge-advanced": "^12.1.0",
|
||||
"object.omit": "^3.0.0",
|
||||
"opn": "^6.0.0",
|
||||
|
@ -131,6 +132,7 @@
|
|||
"tippy.js": "^6.3.1",
|
||||
"tough-cookie": "^4.0.0",
|
||||
"tunnel": "0.0.6",
|
||||
"undici": "^4.13.0",
|
||||
"url-pattern": "^1.0.3",
|
||||
"v-tooltip": "^2.0.3",
|
||||
"video.js": "^7.11.4",
|
||||
|
|
After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 6.6 KiB |
After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 6.6 KiB |
After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 15 KiB |