Compare commits

...

5 Commits

Author SHA1 Message Date
DebaucheryLibrarian 729ca0f968 1.196.1 2021-06-28 02:50:10 +02:00
DebaucheryLibrarian 385dfb9f75 Removed affiliate table in favor of direct campaign URLs. 2021-06-28 02:50:06 +02:00
DebaucheryLibrarian afbae24f43 1.196.0 2021-06-28 00:05:32 +02:00
DebaucheryLibrarian eb7009832a Added rudimentary affiliate banner setup. Separated login and signup disable. Added various tag photos. 2021-06-28 00:05:24 +02:00
DebaucheryLibrarian d1480da076 Added effective date column. Changed warning page theme. 2021-06-19 18:09:58 +02:00
110 changed files with 771 additions and 55 deletions

View File

@ -36,6 +36,7 @@
>Log in</button> >Log in</button>
<router-link <router-link
v-if="$store.state.auth.signup"
:to="{ name: 'signup', query: { ref: $route.query.ref } }" :to="{ name: 'signup', query: { ref: $route.query.ref } }"
class="link link-external signup" class="link link-external signup"
>Sign up</router-link> >Sign up</router-link>
@ -65,7 +66,7 @@ async function login() {
} }
function mounted() { function mounted() {
if (!this.$store.state.auth.enabled) { if (!this.$store.state.auth.login) {
this.$router.replace({ name: 'not-found' }); this.$router.replace({ name: 'not-found' });
} }
} }

View File

@ -44,6 +44,7 @@
>Sign up</button> >Sign up</button>
<router-link <router-link
v-if="$store.state.auth.login"
:to="{ name: 'login', query: { ref: $route.query.ref } }" :to="{ name: 'login', query: { ref: $route.query.ref } }"
class="link link-external login" class="link link-external login"
>Log in</router-link> >Log in</router-link>
@ -74,7 +75,7 @@ async function signup() {
} }
function mounted() { function mounted() {
if (!this.$store.state.auth.enabled) { if (!this.$store.state.auth.signup) {
this.$router.replace({ name: 'not-found' }); this.$router.replace({ name: 'not-found' });
} }
} }

View File

@ -0,0 +1,96 @@
<template>
<a
v-if="campaign"
:href="campaign.url"
target="_blank"
class="campaign"
>
<img
v-if="campaign.banner.entity.type === 'network'"
:src="`/img/banners/${campaign.banner.entity.slug}/${campaign.banner.id}.jpeg`"
class="campaign-banner"
>
<img
v-if="campaign.banner.entity.type === 'channel' && campaign.banner.entity.parent?.type === 'network'"
:src="`/img/banners/${campaign.banner.entity.parent.slug}/${campaign.banner.entity.slug}/${campaign.banner.id}.jpeg`"
class="campaign-banner"
>
</a>
</template>
<script>
function entityCampaign() {
const bannerCampaigns = this.entity.campaigns
.concat(this.entity.children?.flatMap(child => child.campaigns))
.concat(this.entity.parent?.campaigns)
.filter(campaignX => campaignX.banner?.ratio > 3);
if (bannerCampaigns.length > 0) {
return bannerCampaigns[Math.floor(Math.random() * bannerCampaigns.length)];
}
return null;
}
function tagCampaign() {
const campaignBanners = this.tag.banners.filter(banner => banner.campaigns.length > 0 && banner.ratio > 3);
const banner = campaignBanners[Math.floor(Math.random() * campaignBanners.length)];
if (banner?.campaigns.length > 0) {
return {
...banner.campaigns[Math.floor(Math.random() * banner.campaigns.length)],
banner,
};
}
return null;
}
function campaign() {
if (this.entity) {
return this.entityCampaign();
}
if (this.tag) {
return this.tagCampaign();
}
return null;
}
export default {
props: {
entity: {
type: Object,
default: null,
},
tag: {
type: Object,
default: null,
},
},
computed: {
campaign,
},
methods: {
entityCampaign,
tagCampaign,
},
};
</script>
<style lang="scss" scoped>
.campaign {
height: 100%;
display: inline-flex;
flex-grow: 1;
align-items: center;
justify-content: center;
}
.campaign-banner {
max-height: 100%;
max-width: 100%;
}
</style>

View File

@ -67,12 +67,13 @@ export default {
justify-content: center; justify-content: center;
position: absolute; position: absolute;
z-index: 10; z-index: 10;
background: var(--darken-censor); background: var(--background-censor);
backdrop-filter: blur(.25rem);
overflow-y: auto; overflow-y: auto;
} }
.warning { .warning {
color: var(--text-light); color: var(--text);
width: 50rem; width: 50rem;
max-height: 100%; max-height: 100%;
max-width: 100%; max-width: 100%;
@ -87,8 +88,8 @@ export default {
.title { .title {
display: block; display: block;
font-size: 2rem; font-size: 2rem;
margin: 1rem 0 0 0; margin: 1rem 0;
color: var(--text-light); color: var(--text);
text-align: center; text-align: center;
} }
@ -113,7 +114,7 @@ export default {
.rules { .rules {
margin: 0 0 0 1rem; margin: 0 0 0 1rem;
text-align: left; text-align: left;
text-shadow: 0 0 3px var(--darken-extreme); text-shadow: 0 0 3px var(--highlight-strong);
} }
.rule { .rule {
@ -134,16 +135,16 @@ export default {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
border: none; border: none;
border-radius: .25rem;
padding: 0; padding: 0;
position: relative; position: relative;
border-radius: 1rem;
color: var(--lighten-strong);
cursor: pointer; cursor: pointer;
font-size: 1.5rem; font-size: 1.5rem;
text-decoration: none; text-decoration: none;
transition: border .5s ease; transition: border-radius .2s ease;
&.leave { &.leave {
color: var(--shadow-strong);
flex-direction: row; flex-direction: row;
padding: 1rem; padding: 1rem;
@ -151,7 +152,11 @@ export default {
width: 1.5rem; width: 1.5rem;
height: 1.5rem; height: 1.5rem;
margin: 0 1rem 0 0; margin: 0 1rem 0 0;
fill: var(--lighten); fill: var(--shadow);
}
&:hover {
color: var(--text);
} }
} }
@ -161,6 +166,7 @@ export default {
&.straight, &.straight,
&.queer { &.queer {
color: var(--lighten-strong);
background: var(--darken-censor); background: var(--darken-censor);
&:before { &:before {
@ -169,10 +175,18 @@ export default {
height: calc(100% + .25rem); height: calc(100% + .25rem);
position: absolute; position: absolute;
z-index: -1; z-index: -1;
border-radius: 1.1rem;
filter: blur(.25rem); filter: blur(.25rem);
transition: filter .2s ease; transition: filter .2s ease;
} }
&:hover {
color: var(--text-light);
border-radius: 0;
.button-sub {
color: var(--text-light);
}
}
} }
&.straight:before { &.straight:before {
@ -188,14 +202,8 @@ export default {
} }
&:hover { &:hover {
color: var(--text-light);
.button-sub {
color: var(--lighten-strong);
}
.icon { .icon {
fill: var(--text-light); fill: var(--text);
} }
&.straight:before, &.straight:before,
@ -225,7 +233,7 @@ export default {
} }
.preferences { .preferences {
color: var(--lighten); color: var(--shadow);
display: block; display: block;
padding: .5rem 0 1rem 0; padding: .5rem 0 1rem 0;
text-align: center; text-align: center;
@ -234,11 +242,11 @@ export default {
@media(max-width: $breakpoint) { @media(max-width: $breakpoint) {
.title { .title {
font-size: 1.5rem; font-size: 1.75rem;
} }
.logo { .logo {
width: 5rem; width: 5.75rem;
margin: 0 .5rem 0 0; margin: 0 .5rem 0 0;
} }
} }

View File

@ -5,7 +5,7 @@
> >
<div class="info"> <div class="info">
<a <a
:href="entity.url" :href="entityUrl"
target="_blank" target="_blank"
rel="noopener" rel="noopener"
class="link link-child" class="link link-child"
@ -72,6 +72,8 @@
v-else v-else
class="name parent-name" class="name parent-name"
>{{ entity.parent.name }}</h3> >{{ entity.parent.name }}</h3>
<Icon icon="device_hub" />
</router-link> </router-link>
</div> </div>
@ -94,6 +96,10 @@
/> />
</Scroll> </Scroll>
<div class="campaign-container">
<Campaign :entity="entity" />
</div>
<FilterBar <FilterBar
ref="filter" ref="filter"
:fetch-releases="fetchEntity" :fetch-releases="fetchEntity"
@ -122,8 +128,11 @@ import Pagination from '../pagination/pagination.vue';
import Releases from '../releases/releases.vue'; import Releases from '../releases/releases.vue';
import Children from './children.vue'; import Children from './children.vue';
import Scroll from '../scroll/scroll.vue'; import Scroll from '../scroll/scroll.vue';
import Campaign from '../campaigns/campaign.vue';
async function fetchEntity(scroll = true) { async function fetchEntity(scroll = true) {
this.entityUrl = null;
const { entity, totalCount } = await this.$store.dispatch('fetchEntityBySlugAndType', { const { entity, totalCount } = await this.$store.dispatch('fetchEntityBySlugAndType', {
entitySlug: this.$route.params.entitySlug, entitySlug: this.$route.params.entitySlug,
entityType: this.$route.name, entityType: this.$route.name,
@ -136,6 +145,7 @@ async function fetchEntity(scroll = true) {
this.totalCount = totalCount; this.totalCount = totalCount;
this.pageTitle = entity.name; this.pageTitle = entity.name;
this.entityUrl = entity.campaigns.find(campaign => !campaign.banner)?.url || entity.url;
if (scroll && this.$refs.filter?.$el) { if (scroll && this.$refs.filter?.$el) {
this.$refs.filter.$el.scrollIntoView(); this.$refs.filter.$el.scrollIntoView();
@ -160,6 +170,7 @@ export default {
Children, Children,
Releases, Releases,
Scroll, Scroll,
Campaign,
}, },
data() { data() {
return { return {
@ -168,6 +179,7 @@ export default {
totalCount: null, totalCount: null,
limit: Number(this.$route.query.limit) || 20, limit: Number(this.$route.query.limit) || 20,
expanded: false, expanded: false,
entityUrl: null,
}; };
}, },
watch: { watch: {
@ -192,15 +204,17 @@ export default {
} }
.link { .link {
max-width: 20rem; max-width: 15rem;
display: flex; display: flex;
align-items: center; align-items: center;
box-sizing: border-box; box-sizing: border-box;
padding: 1rem; padding: .5rem 1rem;
text-decoration: none; text-decoration: none;
} }
.link-child { .link-child {
flex-shrink: 0;
.icon { .icon {
fill: var(--lighten); fill: var(--lighten);
margin: 0 0 0 1rem; margin: 0 0 0 1rem;
@ -213,7 +227,15 @@ export default {
.link-parent { .link-parent {
flex-direction: row-reverse; flex-direction: row-reverse;
flex-shrink: 0;
margin: 0 0 0 3rem; margin: 0 0 0 3rem;
.icon {
width: 1.25rem;
height: 1.25rem;
fill: var(--lighten);
margin: 0 .5rem 0 0;
}
} }
.logo { .logo {
@ -223,7 +245,7 @@ export default {
} }
.logo-child { .logo-child {
height: 2rem; height: 3rem;
} }
.logo-parent { .logo-parent {
@ -232,6 +254,7 @@ export default {
.favicon { .favicon {
height: 1rem; height: 1rem;
flex-shrink: 0;
} }
.content-inner { .content-inner {
@ -243,6 +266,12 @@ export default {
background: var(--profile); background: var(--profile);
} }
.campaign-container {
background: var(--background-dim);
text-align: center;
padding: .5rem;
}
.releases { .releases {
flex-grow: 1; flex-grow: 1;
} }

View File

@ -2,13 +2,13 @@
<div class="menu"> <div class="menu">
<ul class="menu-items noselect"> <ul class="menu-items noselect">
<router-link <router-link
v-if="auth && me" v-if="login && me"
:to="{ name: 'user', params: { username: me.username } }" :to="{ name: 'user', params: { username: me.username } }"
class="menu-username" class="menu-username"
>{{ me.username }}</router-link> >{{ me.username }}</router-link>
<router-link <router-link
v-else-if="auth" v-else-if="login"
:to="{ name: 'login', query: { ref: $route.path } }" :to="{ name: 'login', query: { ref: $route.path } }"
class="menu-item" class="menu-item"
@click.stop @click.stop
@ -17,7 +17,7 @@
</router-link> </router-link>
<li <li
v-if="auth && me" v-if="login && me"
class="menu-item" class="menu-item"
@click.stop="$store.dispatch('logout')" @click.stop="$store.dispatch('logout')"
> >
@ -89,8 +89,12 @@ function theme(state) {
return state.ui.theme; return state.ui.theme;
} }
function auth(state) { function login(state) {
return state.auth.enabled; return state.auth.login;
}
function signup(state) {
return state.auth.signup;
} }
function me(state) { function me(state) {
@ -108,7 +112,8 @@ function setSfw(enabled) {
export default { export default {
computed: { computed: {
...mapState({ ...mapState({
auth, login,
signup,
sfw, sfw,
theme, theme,
me, me,

View File

@ -47,6 +47,10 @@
@close="$router.replace({ hash: undefined })" @close="$router.replace({ hash: undefined })"
/> />
<div class="campaign-container">
<Campaign :tag="tag" />
</div>
<FilterBar <FilterBar
ref="filter" ref="filter"
:fetch-releases="fetchReleases" :fetch-releases="fetchReleases"
@ -76,6 +80,7 @@ import Album from '../album/album.vue';
import Releases from '../releases/releases.vue'; import Releases from '../releases/releases.vue';
import Pagination from '../pagination/pagination.vue'; import Pagination from '../pagination/pagination.vue';
import Scroll from '../scroll/scroll.vue'; import Scroll from '../scroll/scroll.vue';
import Campaign from '../campaigns/campaign.vue';
const converter = new Converter(); const converter = new Converter();
@ -122,6 +127,7 @@ export default {
Photos, Photos,
Pagination, Pagination,
Scroll, Scroll,
Campaign,
}, },
data() { data() {
return { return {
@ -172,12 +178,14 @@ export default {
@import 'theme'; @import 'theme';
.header { .header {
display: flex;
background: var(--profile); background: var(--profile);
color: var(--text-light); color: var(--text-light);
justify-content: space-between; justify-content: space-between;
} }
.title { .title {
display: inline-block;
padding: .5rem 1rem; padding: .5rem 1rem;
margin: 0; margin: 0;
flex-shrink: 0; flex-shrink: 0;
@ -200,4 +208,11 @@ export default {
.scroll { .scroll {
background: var(--background-dim); background: var(--background-dim);
} }
.campaign-container {
max-height: 90px;
padding: .5rem 1rem 0 1rem;
background: var(--background-dim);
text-align: center;
}
</style> </style>

View File

@ -21,16 +21,17 @@ $breakpoint4: 1500px;
--background-dark: #222; --background-dark: #222;
--darken: rgba(0, 0, 0, .5); --darken: rgba(0, 0, 0, .5);
--darken-strong: rgba(0, 0, 0, .7);
--darken-extreme: rgba(0, 0, 0, .9);
--darken-censor: rgba(0, 0, 0, .95); --darken-censor: rgba(0, 0, 0, .95);
--darken-extreme: rgba(0, 0, 0, .9);
--darken-strong: rgba(0, 0, 0, .7);
--darken-weak: rgba(0, 0, 0, .2); --darken-weak: rgba(0, 0, 0, .2);
--darken-hint: rgba(0, 0, 0, .1); --darken-hint: rgba(0, 0, 0, .1);
--darken-touch: rgba(0, 0, 0, .05); --darken-touch: rgba(0, 0, 0, .05);
--lighten: rgba(255, 255, 255, .5); --lighten-censor: rgba(255, 255, 255, .95);
--lighten-strong: rgba(255, 255, 255, .7);
--lighten-extreme: rgba(255, 255, 255, .9); --lighten-extreme: rgba(255, 255, 255, .9);
--lighten-strong: rgba(255, 255, 255, .7);
--lighten: rgba(255, 255, 255, .5);
--lighten-weak: rgba(255, 255, 255, .2); --lighten-weak: rgba(255, 255, 255, .2);
--lighten-hint: rgba(255, 255, 255, .05); --lighten-hint: rgba(255, 255, 255, .05);
--lighten-touch: rgba(255, 255, 255, .03); --lighten-touch: rgba(255, 255, 255, .03);
@ -58,6 +59,7 @@ $breakpoint4: 1500px;
--text-contrast: #fff; --text-contrast: #fff;
--background: var(--background-light); --background: var(--background-light);
--background-censor: rgba(255, 255, 255, .95);
--background-dim: #f5f5f5; --background-dim: #f5f5f5;
--background-soft: #fdfdfd; --background-soft: #fdfdfd;
@ -71,6 +73,7 @@ $breakpoint4: 1500px;
--crease: #eaeaea; --crease: #eaeaea;
--shadow: rgba(0, 0, 0, .5); --shadow: rgba(0, 0, 0, .5);
--shadow-censor: rgba(0, 0, 0, .95);
--shadow-extreme: rgba(0, 0, 0, .9); --shadow-extreme: rgba(0, 0, 0, .9);
--shadow-strong: rgba(0, 0, 0, .7); --shadow-strong: rgba(0, 0, 0, .7);
--shadow-modest: rgba(0, 0, 0, .3); --shadow-modest: rgba(0, 0, 0, .3);
@ -91,6 +94,7 @@ $breakpoint4: 1500px;
--text-contrast: #222; --text-contrast: #222;
--background: #181818; --background: #181818;
--background-censor: rgba(0, 0, 0, .95);
--background-dim: #111; --background-dim: #111;
--background-soft: #000; --background-soft: #000;

View File

@ -1,4 +1,5 @@
export default { export default {
enabled: window.env.auth, login: window.env.login,
signup: window.env.signup,
user: null, user: null,
}; };

View File

@ -126,6 +126,7 @@ function curateTag(tag) {
}; };
if (tag.releases) curatedTag.releases = tag.releases.map(({ release }) => curateRelease(release)); if (tag.releases) curatedTag.releases = tag.releases.map(({ release }) => curateRelease(release));
if (tag.banners) curatedTag.banners = tag.banners.map(({ banner }) => banner);
if (tag.photos) curatedTag.photos = tag.photos.map(({ media }) => media); if (tag.photos) curatedTag.photos = tag.photos.map(({ media }) => media);
if (tag.poster) curatedTag.poster = tag.poster.media; if (tag.poster) curatedTag.poster = tag.poster.media;

View File

@ -1,6 +1,6 @@
import { graphql } from '../api'; import { graphql } from '../api';
// import { sitesFragment, releaseFields } from '../fragments'; // import { sitesFragment, releaseFields } from '../fragments';
import { releaseFields } from '../fragments'; import { releaseFields, campaignsFragment } from '../fragments';
import { curateEntity } from '../curate'; import { curateEntity } from '../curate';
import getDateRange from '../get-date-range'; import getDateRange from '../get-date-range';
@ -63,8 +63,10 @@ function initEntitiesActions(store, router) {
priority priority
independent independent
hasLogo hasLogo
${campaignsFragment}
} }
} }
${campaignsFragment}
parent { parent {
id id
name name
@ -73,6 +75,7 @@ function initEntitiesActions(store, router) {
url url
independent independent
hasLogo hasLogo
${campaignsFragment}
} }
} }
connection: releasesConnection( connection: releasesConnection(

View File

@ -96,6 +96,62 @@ const actorFields = `
${actorStashesFields} ${actorStashesFields}
`; `;
const campaignsFragment = `
campaigns(filter: {
or: [
{
banner: {
bannersTagsConnection: {
none: {
tag: {
slug: {
in: $exclude
}
}
}
}
}
}
{
bannerExists: false
}
]
}) {
id
url
banner {
id
width
height
ratio
entity {
id
type
name
slug
parent {
id
type
name
slug
}
}
}
entity {
id
type
name
slug
parent {
id
type
name
slug
}
}
}
`;
const releaseActorsFragment = ` const releaseActorsFragment = `
actors: releasesActors(orderBy: ACTOR_BY_ACTOR_ID__GENDER_ASC) { actors: releasesActors(orderBy: ACTOR_BY_ACTOR_ID__GENDER_ASC) {
actor { actor {
@ -480,6 +536,7 @@ function getIncludedActors(router) {
export { export {
actorFields, actorFields,
actorStashesFields, actorStashesFields,
campaignsFragment,
releaseActorsFragment, releaseActorsFragment,
releaseFields, releaseFields,
releaseTagsFragment, releaseTagsFragment,

View File

@ -26,6 +26,31 @@ const dateRanges = {
}), }),
}; };
/* requires PostgreSQL 12.x> not available in production yet
const dateRanges = {
latest: () => ({
after: '1900-01-01',
before: dayjs.utc().toDate(),
orderBy: ['EFFECTIVE_DATE_DESC'],
}),
upcoming: () => ({
after: dayjs.utc().toDate(),
before: '2100-01-01',
orderBy: ['EFFECTIVE_DATE_DESC'],
}),
new: () => ({
after: '1900-01-01 00:00:00',
before: '2100-01-01',
orderBy: ['CREATED_AT_DESC', 'EFFECTIVE_DATE_ASC'],
}),
all: () => ({
after: '1900-01-01',
before: '2100-01-01',
orderBy: ['EFFECTIVE_DATE_DESC'],
}),
};
*/
function getDateRange(range) { function getDateRange(range) {
return (dateRanges[range] || dateRanges.all)(); return (dateRanges[range] || dateRanges.all)();
} }

View File

@ -103,6 +103,56 @@ function initTagsActions(store, _router) {
} }
} }
} }
banners: bannersTags(filter: {
banner: {
bannersTagsConnection: {
none: {
tag: {
slug: {
in: $exclude
}
}
}
}
}
}) {
banner {
id
width
height
ratio
entity {
id
type
name
slug
independent
parent {
id
type
name
slug
independent
}
}
campaigns {
id
url
entity {
id
type
name
slug
parent {
id
type
name
slug
}
}
}
}
}
scenesConnection( scenesConnection(
filter: { filter: {
date: { date: {

View File

@ -35,7 +35,8 @@ module.exports = {
secretKey: 'abcdefghijklmnopqrstuvwxyz1234567890ABCD', secretKey: 'abcdefghijklmnopqrstuvwxyz1234567890ABCD',
}, },
auth: { auth: {
enabled: true, login: true,
signup: true,
}, },
exclude: { exclude: {
channels: [ channels: [

View File

@ -1274,11 +1274,78 @@ exports.up = knex => Promise.resolve()
.notNullable() .notNullable()
.defaultTo(knex.fn.now()); .defaultTo(knex.fn.now());
})) }))
// SEARCH .then(() => knex.schema.createTable('banners', (table) => {
table.string('id')
.primary()
.unique()
.notNullable();
table.integer('width')
.notNullable();
table.integer('height')
.notNullable();
table.integer('entity_id', 12)
.references('id')
.inTable('entities');
table.text('comment');
table.datetime('created_at')
.notNullable()
.defaultTo(knex.fn.now());
}))
.then(() => knex.schema.createTable('banners_tags', (table) => {
table.increments('id');
table.string('banner_id')
.notNullable()
.references('id')
.inTable('banners');
table.integer('tag_id')
.notNullable()
.references('id')
.inTable('tags');
table.unique(['banner_id', 'tag_id']);
table.datetime('created_at')
.notNullable()
.defaultTo(knex.fn.now());
}))
.then(() => knex.schema.createTable('campaigns', (table) => {
table.increments('id');
table.integer('entity_id', 12)
.notNullable()
.references('id')
.inTable('entities');
table.string('banner_id')
.references('id')
.inTable('banners');
table.text('url')
.notNullable();
table.text('comment');
table.datetime('created_at')
.notNullable()
.defaultTo(knex.fn.now());
}))
// SEARCH AND SORT
.then(() => { // eslint-disable-line arrow-body-style .then(() => { // eslint-disable-line arrow-body-style
// allow vim fold // allow vim fold
return knex.raw(` return knex.raw(`
ALTER TABLE releases_search ADD COLUMN document tsvector; ALTER TABLE releases_search ADD COLUMN document tsvector;
/* allow scenes without dates to be mixed inbetween scenes with dates */
ALTER TABLE releases
ADD COLUMN effective_date timestamptz
GENERATED ALWAYS AS (COALESCE(date, created_at)) STORED;
`); `);
}) })
// INDEXES // INDEXES
@ -1288,6 +1355,9 @@ exports.up = knex => Promise.resolve()
CREATE UNIQUE INDEX unique_actor_slugs_network ON actors (slug, entity_id, entry_id); CREATE UNIQUE INDEX unique_actor_slugs_network ON actors (slug, entity_id, entry_id);
CREATE UNIQUE INDEX unique_actor_slugs ON actors (slug) WHERE entity_id IS NULL; CREATE UNIQUE INDEX unique_actor_slugs ON actors (slug) WHERE entity_id IS NULL;
CREATE UNIQUE INDEX unique_entity_campaigns_banner ON campaigns (entity_id, url, banner_id);
CREATE UNIQUE INDEX unique_entity_campaigns ON campaigns (entity_id, url) WHERE banner_id IS NULL;
CREATE UNIQUE INDEX releases_search_unique ON releases_search (release_id); CREATE UNIQUE INDEX releases_search_unique ON releases_search (release_id);
CREATE INDEX releases_search_index ON releases_search USING GIN (document); CREATE INDEX releases_search_index ON releases_search USING GIN (document);
`); `);
@ -1476,6 +1546,10 @@ exports.up = knex => Promise.resolve()
CREATE FUNCTION releases_is_new(release releases) RETURNS boolean AS $$ CREATE FUNCTION releases_is_new(release releases) RETURNS boolean AS $$
SELECT EXISTS(SELECT true WHERE (SELECT id FROM batches ORDER BY created_at DESC LIMIT 1) = release.created_batch_id); SELECT EXISTS(SELECT true WHERE (SELECT id FROM batches ORDER BY created_at DESC LIMIT 1) = release.created_batch_id);
$$ LANGUAGE sql STABLE; $$ LANGUAGE sql STABLE;
CREATE FUNCTION banners_ratio(banner banners) RETURNS real AS $$
SELECT ROUND(banner.width::decimal / banner.height::decimal, 2);
$$ LANGUAGE SQL STABLE;
`); `);
}) })
// POLICIES // POLICIES
@ -1642,6 +1716,9 @@ exports.down = (knex) => { // eslint-disable-line arrow-body-style
DROP TABLE IF EXISTS chapters_posters CASCADE; DROP TABLE IF EXISTS chapters_posters CASCADE;
DROP TABLE IF EXISTS chapters_photos CASCADE; DROP TABLE IF EXISTS chapters_photos CASCADE;
DROP TABLE IF EXISTS banners_tags CASCADE;
DROP TABLE IF EXISTS banners CASCADE;
DROP TABLE IF EXISTS campaigns CASCADE;
DROP TABLE IF EXISTS batches CASCADE; DROP TABLE IF EXISTS batches CASCADE;
DROP TABLE IF EXISTS actors_avatars CASCADE; DROP TABLE IF EXISTS actors_avatars CASCADE;
@ -1654,6 +1731,7 @@ exports.down = (knex) => { // eslint-disable-line arrow-body-style
DROP TABLE IF EXISTS entities_tags CASCADE; DROP TABLE IF EXISTS entities_tags CASCADE;
DROP TABLE IF EXISTS entities_social CASCADE; DROP TABLE IF EXISTS entities_social CASCADE;
DROP TABLE IF EXISTS sites_tags CASCADE; DROP TABLE IF EXISTS sites_tags CASCADE;
DROP TABLE IF EXISTS sites_social CASCADE; DROP TABLE IF EXISTS sites_social CASCADE;
DROP TABLE IF EXISTS networks_social CASCADE; DROP TABLE IF EXISTS networks_social CASCADE;

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "traxxx", "name": "traxxx",
"version": "1.195.0", "version": "1.196.1",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {

View File

@ -1,6 +1,6 @@
{ {
"name": "traxxx", "name": "traxxx",
"version": "1.195.0", "version": "1.196.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": {

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View File

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 444 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Some files were not shown because too many files have changed in this diff Show More