From 23803423282a6fa2235b93af0c35e6b3667faab0 Mon Sep 17 00:00:00 2001 From: DebaucheryLibrarian Date: Thu, 22 Jan 2026 05:58:05 +0100 Subject: [PATCH] Added improved affiliate URL logic for entities. --- pages/entities/@entitySlug/+Page.vue | 4 ++ src/affiliates.js | 78 ++++++++++++++++++++++++++++ src/entities.js | 9 +++- src/scenes.js | 51 +----------------- static | 2 +- 5 files changed, 92 insertions(+), 52 deletions(-) create mode 100644 src/affiliates.js diff --git a/pages/entities/@entitySlug/+Page.vue b/pages/entities/@entitySlug/+Page.vue index 66edde4..114382e 100644 --- a/pages/entities/@entitySlug/+Page.vue +++ b/pages/entities/@entitySlug/+Page.vue @@ -168,6 +168,9 @@ const entityUrl = (() => { return null; } + return entity.affiliateUrl || entity.url; + + /* // affiliate might be inherited, only use full URL when directly associated if (entity.affiliate?.url && entity.affiliate.entityId === entity.id) { return entity.affiliate.url; @@ -183,6 +186,7 @@ const entityUrl = (() => { } return entity.url; + */ })(); diff --git a/src/affiliates.js b/src/affiliates.js new file mode 100644 index 0000000..c913f2f --- /dev/null +++ b/src/affiliates.js @@ -0,0 +1,78 @@ +function getWatchUrl(scene) { + if (scene.url) { + return scene.url; + } + + if (scene.channel && (scene.channel.isIndependent || scene.channel.type === 'network')) { + return scene.channel.url; + } + + if (scene.network) { + return scene.network.url; + } + + return null; +} + +export function getAffiliateSceneUrl(scene) { + const watchUrl = getWatchUrl(scene); + + if (!watchUrl) { + return null; + } + + if (!scene.affiliate) { + return watchUrl; + } + + if (scene.affiliate.url?.includes('/track') + && scene.affiliate.parameters.scene !== false + && (!scene.channel.isIndependent || scene.channel.id === scene.affiliate.entityId)) { // standard NATS redirect + const { pathname, search } = new URL(watchUrl); + + return `${scene.affiliate.url}${pathname.replace(/^\/trial/, '')}${search}`; // replace needed for Jules Jordan, verify behavior on other sites + } + + if (scene.affiliate.parameters.query) { // used by e.g. Bang + const newParams = new URLSearchParams({ + ...Object.fromEntries(new URL(watchUrl).searchParams), + ...Object.fromEntries(new URLSearchParams(scene.affiliate.parameters.query)), + }); + + return `${watchUrl}?${newParams.toString()}`; + } + + return watchUrl; +} + +export function getAffiliateEntityUrl(entity) { + if (!entity.affiliate) { + return entity.url; + } + + if (entity.id === entity.affiliate.entityId) { + return entity.affiliate.url; + } + + if (entity.isIndependent) { + return entity.url; + } + + if (entity.affiliate.url?.includes('/track') + && entity.affiliate.parameters.channel !== false) { + const { pathname, search } = new URL(entity.url); + + return `${entity.affiliate.url}${pathname.replace(/^\/trial/, '')}${search}`; // replace needed for Jules Jordan, verify behavior on other sites + } + + if (entity.affiliate.parameters.query) { // used by e.g. Bang + const newParams = new URLSearchParams({ + ...Object.fromEntries(new URL(entity.url).searchParams), + ...Object.fromEntries(new URLSearchParams(entity.affiliate.parameters.query)), + }); + + return `${entity.url}?${newParams.toString()}`; + } + + return entity.url; +} diff --git a/src/entities.js b/src/entities.js index 2f3fa98..f82f385 100644 --- a/src/entities.js +++ b/src/entities.js @@ -2,6 +2,7 @@ import knex from './knex.js'; import redis from './redis.js'; import initLogger from './logger.js'; import entityPrefixes from './entities-prefixes.js'; +import { getAffiliateEntityUrl } from './affiliates.js'; const logger = initLogger(); @@ -10,7 +11,7 @@ export function curateEntity(entity, context) { return null; } - return { + const curatedEntity = { id: entity.id, name: entity.name, slug: entity.slug, @@ -29,7 +30,7 @@ export function curateEntity(entity, context) { id: entity.affiliate.id, entityId: entity.affiliate.entity_id, url: entity.affiliate.url, - parameters: entity.affiliate.parameters, + parameters: entity.affiliate.parameters || {}, } : null, ...context?.append?.[entity.id], alerts: { @@ -37,6 +38,10 @@ export function curateEntity(entity, context) { multi: context?.alerts?.filter((alert) => !alert.is_only).flatMap((alert) => alert.alert_ids) || [], }, }; + + curatedEntity.affiliateUrl = getAffiliateEntityUrl(curatedEntity, curatedEntity); + + return curatedEntity; } export async function fetchEntities(options = {}) { diff --git a/src/scenes.js b/src/scenes.js index b64f5bb..32d03fb 100644 --- a/src/scenes.js +++ b/src/scenes.js @@ -1,5 +1,4 @@ import config from 'config'; -import util from 'util'; /* eslint-disable-line no-unused-vars */ import { MerkleJson } from 'merkle-json'; import { knexQuery as knex, knexOwner, knexManticore } from './knex.js'; @@ -15,57 +14,11 @@ import escape from '../utils/escape-manticore.js'; import promiseProps from '../utils/promise-props.js'; import initLogger from './logger.js'; import { curateRevision } from './revisions.js'; +import { getAffiliateSceneUrl } from './affiliates.js'; const logger = initLogger(); const mj = new MerkleJson(); -function getWatchUrl(scene) { - if (scene.url) { - return scene.url; - } - - if (scene.channel && (scene.channel.isIndependent || scene.channel.type === 'network')) { - return scene.channel.url; - } - - if (scene.network) { - return scene.network.url; - } - - return null; -} - -function getAffiliateUrl(scene) { - const watchUrl = getWatchUrl(scene); - - if (!watchUrl) { - return null; - } - - if (!scene.affiliate) { - return watchUrl; - } - - if (scene.affiliate.url?.includes('/track') - && scene.affiliate.parameters.scene !== false - && (!scene.channel.isIndependent || scene.channel.id === scene.affiliate.entityId)) { // standard NATS redirect - const { pathname, search } = new URL(watchUrl); - - return `${scene.affiliate.url}${pathname.replace(/^\/trial/, '')}${search}`; // replace needed for Jules Jordan, verify behavior on other sites - } - - if (scene.affiliate.parameters.query) { // used by e.g. Bang - const newParams = new URLSearchParams({ - ...Object.fromEntries(new URL(watchUrl).searchParams), - ...Object.fromEntries(new URLSearchParams(scene.affiliate.parameters.query)), - }); - - return `${watchUrl}?${newParams.toString()}`; - } - - return watchUrl; -} - function curateScene(rawScene, assets) { if (!rawScene) { return null; @@ -164,7 +117,7 @@ function curateScene(rawScene, assets) { isNew: assets.lastBatchId === rawScene.created_batch_id, }; - curatedScene.watchUrl = getAffiliateUrl(curatedScene); + curatedScene.watchUrl = getAffiliateSceneUrl(curatedScene); return curatedScene; } diff --git a/static b/static index 323fb4c..8ba0b20 160000 --- a/static +++ b/static @@ -1 +1 @@ -Subproject commit 323fb4c9220637d48a1f7516bbfbfafdfdb45ccc +Subproject commit 8ba0b203fad2fa85624590a2547c1ae71f8fb481