Added Gamma banner downloader.

This commit is contained in:
DebaucheryLibrarian
2026-03-02 03:08:26 +01:00
parent ffcfae69d5
commit e029ca7fd0

119
src/tools/gamma_banners.js Normal file
View File

@@ -0,0 +1,119 @@
'use strict';
const unprint = require('unprint');
const fs = require('fs');
const { Readable } = require('stream');
const { pipeline } = require('stream/promises');
const knex = require('../knex');
const argv = require('../argv');
const slugify = require('../utils/slugify');
const apiUrl = 'https://vjoc5ygk89-dsn.algolia.net/1/indexes/*/queries?x-algolia-agent=Algolia%20for%20JavaScript%20(3.33.0)%3B%20Browser%20(lite)%3B%20react%20(16.8.6)%3B%20react-instantsearch%20(5.7.0)%3B%20JS%20Helper%20(2.28.1)&x-algolia-application-id=VJOC5YGK89&x-algolia-api-key=c5546bdfb4d3f31daf49ed3bb1463561';
async function fetchBanners() {
const res = await unprint.post(
apiUrl,
{
requests: [
{
indexName: 'creatives',
params: new URLSearchParams({
hitsPerPage: 1000,
maxValuesPerFacet: 100,
page: 0,
filters: '(ProgramType:Legacy OR ProgramType:Internal) AND NOT OverlayActive:false',
facets: '["SceneActors","SceneCategories","ProgramName","Size","Niche","MediaExt","SiteTag","OverlayName"]',
facetFilters: `[["SiteTag:${argv.site}"],["MediaExt:jpg", "MediaExt:png", "MediaExt:gif"],["ProgramName:${argv.program || 'Fame'}"]]`,
}).toString(),
},
],
},
{
headers: {
'content-type': 'application/x-www-form-urlencoded',
referer: 'https://creatives.gammae.com/',
},
},
);
if (res.ok && res.data.results[0]) {
return res.data.results[0].hits;
}
console.error(`Failed API request (${res.status}): ${res.body}`);
return null;
}
async function matchTags(rawTags) {
if (!rawTags) {
return [];
}
const tags = rawTags
.map((tag) => tag?.trim().match(/[a-z0-9()]+/ig)?.join(' ').toLowerCase())
.filter(Boolean);
const tagEntries = await knex('tags')
.select('tags.slug', 'aliases.slug as alias_slug')
.whereIn(knex.raw('lower(tags.name)'), tags)
.leftJoin('tags as aliases', 'aliases.id', 'tags.alias_for')
.orderByRaw('CASE WHEN tags.alias_for IS NOT NULL THEN aliases.priority ELSE tags.priority END DESC');
return tagEntries.map((tagEntry) => tagEntry.alias_slug || tagEntry.slug);
}
async function init() {
const banners = await fetchBanners();
if (!banners) {
return;
}
await banners.reduce(async (chain, banner) => {
await chain;
const channel = slugify(banner.SiteTag, '');
const url = `https://cdn.banhq.com${banner.MediaLocation}`;
const tags = await matchTags([
...banner.Tags?.map((tag) => tag.Value) || [],
...banner.SceneCategories || [],
banner.Niche,
].filter(Boolean));
const fileTags = tags.slice(0, 4).join('_');
const fileActors = banner.SceneActors?.slice(0, 2).map((actor) => slugify(actor, '_')).join('_');
const filename = `${channel}_${banner.Width}_${banner.Height}_${fileActors || banner.MediaID}${fileTags ? `-${fileTags}` : ''}.${banner.MediaExt}`;
const filepath = `/tmp/gamma/${channel}/${filename}`;
if (argv.inspect) {
console.log(banner);
}
if (argv.preview) {
console.log(`Preview ${url}: ${filepath}`);
return;
}
await fs.promises.mkdir(`/tmp/gamma/${channel}`, { recursive: true });
const res = await fetch(url);
if (res.ok && res.body) {
const writer = fs.createWriteStream(filepath);
await pipeline(Readable.fromWeb(res.body), writer);
console.log(`Saved ${url} to ${filepath}`);
} else {
console.log(`Failed to fetch ${url}`);
}
}, Promise.resolve());
await knex.destroy();
}
init();