+
+
+
diff --git a/pages/updates/+onBeforeRender.js b/pages/updates/+onBeforeRender.js
index 056ca50..6717c02 100644
--- a/pages/updates/+onBeforeRender.js
+++ b/pages/updates/+onBeforeRender.js
@@ -1,10 +1,31 @@
import { fetchScenes } from '#/src/scenes.js';
import { curateScenesQuery } from '#/src/web/scenes.js';
-import { getRandomCampaign } from '#/src/campaigns.js';
+import { getRandomCampaigns } from '#/src/campaigns.js';
export async function onBeforeRender(pageContext) {
const withQuery = Object.hasOwn(pageContext.urlParsed.search, 'q');
+ const [
+ sceneResults,
+ campaigns,
+ ] = await Promise.all([
+ fetchScenes(await curateScenesQuery({
+ ...pageContext.urlQuery,
+ scope: pageContext.routeParams.scope || 'latest',
+ isShowcased: withQuery ? null : true,
+ tagFilter: pageContext.tagFilter,
+ }), {
+ page: Number(pageContext.routeParams.page) || 1,
+ limit: Number(pageContext.urlParsed.search.limit) || 29,
+ aggregate: withQuery,
+ }, pageContext.user),
+ getRandomCampaigns([
+ { minRatio: 1.5 },
+ { minRatio: 0.75, maxRatio: 1.25 },
+ { minRatio: 1.5 },
+ ]),
+ ]);
+
const {
scenes,
aggTags,
@@ -12,20 +33,10 @@ export async function onBeforeRender(pageContext) {
aggActors,
limit,
total,
- } = await fetchScenes(await curateScenesQuery({
- ...pageContext.urlQuery,
- scope: pageContext.routeParams.scope || 'latest',
- isShowcased: withQuery ? null : true,
- tagFilter: pageContext.tagFilter,
- }), {
- page: Number(pageContext.routeParams.page) || 1,
- limit: Number(pageContext.urlParsed.search.limit) || 29,
- aggregate: withQuery,
- }, pageContext.user);
+ } = sceneResults;
- // const campaignIndex = Math.floor(Math.random() * (scenes.length - 5)) + 5;
const campaignIndex = Math.floor((Math.random() * (0.5 - 0.2) + 0.2) * scenes.length);
- const sceneCampaign = await getRandomCampaign({ minRatio: 0.75, maxRatio: 1.25 });
+ const [scopeCampaign, sceneCampaign, paginationCampaign] = campaigns;
return {
pageContext: {
@@ -37,10 +48,12 @@ export async function onBeforeRender(pageContext) {
aggActors,
limit,
total,
- campaigns: {
- index: campaignIndex,
- scenes: sceneCampaign,
- },
+ },
+ campaigns: {
+ index: campaignIndex,
+ scope: scopeCampaign,
+ scenes: scenes.length > 5 && sceneCampaign,
+ pagination: paginationCampaign,
},
},
};
diff --git a/renderer/+config.h.js b/renderer/+config.h.js
index 3e26487..166f6c4 100644
--- a/renderer/+config.h.js
+++ b/renderer/+config.h.js
@@ -6,6 +6,7 @@ export default {
'urlParsed',
'env',
'user',
+ 'campaigns',
'meta',
],
};
diff --git a/src/campaigns.js b/src/campaigns.js
index b6ee7a8..6eb5745 100644
--- a/src/campaigns.js
+++ b/src/campaigns.js
@@ -15,6 +15,7 @@ function curateCampaign(campaign) {
return {
id: campaign.id,
url: campaign.url,
+ entity: campaign.entity && curateEntity({ ...campaign.entity, parent: campaign.parent_entity }),
banner: campaign.banner && {
id: campaign.banner.id,
type: campaign.banner.type,
@@ -37,8 +38,8 @@ function curateCampaign(campaign) {
}
export async function getRandomCampaign(options = {}) {
- const rawCampaigns = await redis.hGetAll('traxxx:campaigns');
- const campaigns = Object.values(rawCampaigns).map((rawCampaign) => JSON.parse(rawCampaign));
+ const campaigns = options.campaigns
+ || await redis.hGetAll('traxxx:campaigns').then((rawCampaigns) => Object.values(rawCampaigns).map((rawCampaign) => JSON.parse(rawCampaign)));
const validCampaigns = campaigns.filter((campaign) => {
if (options.minRatio && (!campaign.banner || campaign.banner.ratio < options.minRatio)) {
@@ -49,12 +50,34 @@ export async function getRandomCampaign(options = {}) {
return false;
}
+ if (options.entityIds && !options.entityIds.some((entityId) => campaign.entity.id === entityId || campaign.entity.parent?.id === entityId)) {
+ return false;
+ }
+
return true;
});
- const randomCampaign = validCampaigns[crypto.randomInt(validCampaigns.length)];
+ const primaryCampaigns = validCampaigns.filter((campaign) => campaign.entity.id === options.entityIds?.[0]);
- return randomCampaign;
+ if (validCampaigns.length > 0) {
+ const randomCampaign = primaryCampaigns.length > 0
+ ? primaryCampaigns[crypto.randomInt(primaryCampaigns.length)]
+ : validCampaigns[crypto.randomInt(validCampaigns.length)];
+
+ return randomCampaign;
+ }
+
+ return null;
+}
+
+export async function getRandomCampaigns(allOptions = []) {
+ const rawCampaigns = await redis.hGetAll('traxxx:campaigns');
+ const campaigns = Object.values(rawCampaigns).map((rawCampaign) => JSON.parse(rawCampaign));
+
+ return Promise.all(allOptions.map(async (options) => getRandomCampaign({
+ ...options,
+ campaigns,
+ })));
}
export async function cacheCampaigns() {
@@ -64,17 +87,29 @@ export async function cacheCampaigns() {
'campaigns.*',
knex.raw('row_to_json(affiliates) as affiliate'),
knex.raw('row_to_json(banners) as banner'),
- knex.raw('row_to_json(entities) as banner_entity'),
- knex.raw('row_to_json(parents) as banner_parent_entity'),
+ knex.raw('row_to_json(entities) as entity'),
+ knex.raw('row_to_json(parents) as parent_entity'),
+ knex.raw('row_to_json(banner_entities) as banner_entity'),
+ knex.raw('row_to_json(banner_parents) as banner_parent_entity'),
knex.raw('json_agg(tags.slug) filter (where tags.id is not null) as banner_tags'),
)
.leftJoin('affiliates', 'affiliates.id', 'campaigns.affiliate_id')
.leftJoin('banners', 'banners.id', 'campaigns.banner_id')
.leftJoin('banners_tags', 'banners_tags.banner_id', 'banners.id')
.leftJoin('tags', 'tags.id', 'banners_tags.tag_id')
- .leftJoin('entities', 'entities.id', 'banners.entity_id')
+ .leftJoin('entities', 'entities.id', 'campaigns.entity_id')
.leftJoin('entities as parents', 'parents.id', 'entities.parent_id')
- .groupBy('campaigns.id', 'affiliates.id', 'banners.id', 'entities.id', 'parents.id');
+ .leftJoin('entities as banner_entities', 'banner_entities.id', 'banners.entity_id')
+ .leftJoin('entities as banner_parents', 'banner_parents.id', 'banner_entities.parent_id')
+ .groupBy(
+ 'campaigns.id',
+ 'affiliates.id',
+ 'entities.id',
+ 'parents.id',
+ 'banners.id',
+ 'banner_entities.id',
+ 'banner_parents.id',
+ );
await redis.del('traxxx:campaigns');
diff --git a/src/entities.js b/src/entities.js
index 3e0847c..9cb6196 100644
--- a/src/entities.js
+++ b/src/entities.js
@@ -30,16 +30,24 @@ export async function fetchEntities(options) {
if (options.query) {
builder.where((whereBuilder) => {
whereBuilder
- .whereILike('entities.name', `%${options.query}%`)
- .orWhereILike('entities.slug', `%${options.query}%`);
+ .where((subBuilder) => {
+ subBuilder
+ .whereILike('entities.name', `%${options.query}%`)
+ .orWhereILike('entities.slug', `%${options.query}%`);
+ })
+ .whereNot('entities.type', 'info');
});
}
if (options.type === 'primary') {
builder
- .where('entities.type', 'network')
- .orWhere('entities.independent', true)
- .orWhereNull('entities.parent_id');
+ .where((subBuilder) => {
+ subBuilder
+ .where('entities.type', 'network')
+ .orWhere('entities.independent', true)
+ .orWhereNull('entities.parent_id');
+ })
+ .whereNot('entities.type', 'info');
return;
}
diff --git a/src/scenes.js b/src/scenes.js
index 37ea3f3..d98c1ec 100644
--- a/src/scenes.js
+++ b/src/scenes.js
@@ -73,7 +73,8 @@ function curateScene(rawScene, assets) {
poster: curateMedia(assets.poster),
trailer: curateMedia(assets.trailer),
teaser: curateMedia(assets.teaser),
- photos: assets.photos.map((photo) => curateMedia(photo)),
+ photos: assets.photos?.map((photo) => curateMedia(photo)) || [],
+ caps: assets.caps?.map((cap) => curateMedia(cap)) || [],
stashes: assets.stashes?.map((stash) => curateStash(stash)) || [],
createdBatchId: rawScene.created_batch_id,
updatedBatchId: rawScene.updated_batch_id,
@@ -92,6 +93,7 @@ export async function fetchScenesById(sceneIds, { reqUser, ...context } = {}) {
series,
posters,
photos,
+ caps,
trailers,
teasers,
stashes,
@@ -125,24 +127,24 @@ export async function fetchScenesById(sceneIds, { reqUser, ...context } = {}) {
.whereNotNull('tags.id')
.whereIn('release_id', sceneIds)
.orderBy('priority', 'desc'),
- movies: knex('movies_scenes')
+ movies: context.includePartOf ? knex('movies_scenes')
.select('movies_scenes.scene_id', 'movies.*', knex.raw('json_agg(media) as movie_covers'))
.leftJoin('movies', 'movies.id', 'movies_scenes.movie_id')
.leftJoin('movies_covers', 'movies_covers.movie_id', 'movies.id')
.leftJoin('media', 'media.id', 'movies_covers.media_id')
.whereIn('scene_id', sceneIds)
- .groupBy('movies.id', 'movies_scenes.scene_id'),
- series: knex('series_scenes')
+ .groupBy('movies.id', 'movies_scenes.scene_id') : [],
+ series: context.includePartOf ? knex('series_scenes')
.select('series_scenes.scene_id', 'series.*', knex.raw('row_to_json(media) as serie_poster'))
.leftJoin('series', 'series.id', 'series_scenes.serie_id')
.leftJoin('series_posters', 'series_posters.serie_id', 'series.id')
.leftJoin('media', 'media.id', 'series_posters.media_id')
.whereIn('scene_id', sceneIds)
- .groupBy('series.id', 'series_scenes.scene_id', 'media.*'),
+ .groupBy('series.id', 'series_scenes.scene_id', 'media.*') : [],
posters: knex('releases_posters')
.whereIn('release_id', sceneIds)
.leftJoin('media', 'media.id', 'releases_posters.media_id'),
- photos: knex.transaction(async (trx) => {
+ photos: context.includeAssets ? knex.transaction(async (trx) => {
if (reqUser) {
await trx.select(knex.raw('set_config(\'user.id\', :userId, true)', { userId: reqUser.id }));
}
@@ -151,8 +153,18 @@ export async function fetchScenesById(sceneIds, { reqUser, ...context } = {}) {
.leftJoin('media', 'media.id', 'releases_photos.media_id')
.whereIn('release_id', sceneIds)
.orderBy('index');
- }),
- trailers: knex.transaction(async (trx) => {
+ }) : [],
+ caps: context.includeAssets ? knex.transaction(async (trx) => {
+ if (reqUser) {
+ await trx.select(knex.raw('set_config(\'user.id\', :userId, true)', { userId: reqUser.id }));
+ }
+
+ return trx('releases_caps')
+ .leftJoin('media', 'media.id', 'releases_caps.media_id')
+ .whereIn('release_id', sceneIds)
+ .orderBy('index');
+ }) : [],
+ trailers: context.includeAssets ? knex.transaction(async (trx) => {
if (reqUser) {
await trx.select(knex.raw('set_config(\'user.id\', :userId, true)', { userId: reqUser.id }));
}
@@ -160,8 +172,8 @@ export async function fetchScenesById(sceneIds, { reqUser, ...context } = {}) {
return trx('releases_trailers')
.whereIn('release_id', sceneIds)
.leftJoin('media', 'media.id', 'releases_trailers.media_id');
- }),
- teasers: knex.transaction(async (trx) => {
+ }) : [],
+ teasers: context.includeAssets ? knex.transaction(async (trx) => {
if (reqUser) {
await trx.select(knex.raw('set_config(\'user.id\', :userId, true)', { userId: reqUser.id }));
}
@@ -169,7 +181,7 @@ export async function fetchScenesById(sceneIds, { reqUser, ...context } = {}) {
return trx('releases_teasers')
.whereIn('release_id', sceneIds)
.leftJoin('media', 'media.id', 'releases_teasers.media_id');
- }),
+ }) : [],
lastBatch: knex('batches')
.select('id')
.where('showcased', true)
@@ -205,6 +217,7 @@ export async function fetchScenesById(sceneIds, { reqUser, ...context } = {}) {
const sceneSeries = series.filter((serie) => serie.scene_id === sceneId);
const scenePoster = posters.find((poster) => poster.release_id === sceneId);
const scenePhotos = photos.filter((photo) => photo.release_id === sceneId);
+ const sceneCaps = caps.filter((cap) => cap.release_id === sceneId);
const sceneTrailers = trailers.find((trailer) => trailer.release_id === sceneId);
const sceneTeasers = teasers.find((teaser) => teaser.release_id === sceneId);
const sceneStashes = stashes.filter((stash) => stash.scene_id === sceneId);
@@ -219,6 +232,7 @@ export async function fetchScenesById(sceneIds, { reqUser, ...context } = {}) {
series: sceneSeries,
poster: scenePoster,
photos: scenePhotos,
+ caps: sceneCaps,
trailer: sceneTrailers,
teaser: sceneTeasers,
stashes: sceneStashes,