PronounsPage/server/cards.ts
Valentyne Stigloher 9b6bff27f3 (aws) migrate to v3
payloads are now streamed, which is a bit cumbersome with express,
but according to https://stackoverflow.com/questions/76142043/getting-a-readable-from-getobject-in-aws-s3-sdk-v3
it is safe to cast to a NodeJsClient
2024-03-28 13:56:07 +01:00

110 lines
3.5 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import './setup.ts';
import type { Screenshot } from 'pageres';
import Pageres from 'pageres';
import * as Sentry from '@sentry/node';
import isHighLoadTime from './overload.js';
import type { Database } from './db.ts';
import dbConnection from './db.ts';
import allLocales from '../locale/locales.ts';
import { ulid } from 'ulid';
import { awsConfig, awsParams } from './aws.ts';
import { S3 } from '@aws-sdk/client-s3';
const s3 = new S3(awsConfig);
const urlBases: Record<string, string> = {};
for (const { code, url } of allLocales) {
urlBases[code] = `${url}/card/@`; // 'http://localhost:3000/card/@'
}
const domainLocaleMap: Record<string, string> = {};
for (const { code, url } of allLocales) {
domainLocaleMap[url.replace(/^https?:\/\//, '')] = code;
}
const sleep = (ms: number): Promise<void> => new Promise((res) => setTimeout(res, ms));
const modes = ['light', 'dark'] as const;
const shoot = async (db: Database, mode: 'light' | 'dark'): Promise<void> => {
const profiles = (await db.all<{ id: string, locale: string, username: string }>(`
SELECT profiles.id, profiles.locale, users.username
FROM profiles
LEFT JOIN users on profiles.userId = users.id
WHERE profiles.${mode === 'dark' ? 'cardDark' : 'card'} = ''
ORDER BY RANDOM()
LIMIT 6
`)).filter(({ locale }) => !isHighLoadTime(locale));
if (profiles.length === 0) {
console.log('No profiles in the queue');
return;
}
const results: Record<string, Screenshot> = {};
try {
const pr = new Pageres({
darkMode: mode === 'dark',
delay: 3,
scale: 1.5,
});
for (const { locale, username } of profiles) {
console.log(`Shooting @${username} (${locale}, ${mode})`);
pr.src(urlBases[locale] + username, ['1024x300']);
}
for (const buffer of await pr.run()) {
const [, domain, username] = buffer.filename.match(/(.*)!card!@(.*)-1024x300\.png/)!;
const locale = domainLocaleMap[domain];
results[`${locale}/${username.replace(/[^A-Za-z0-9.-]/g, '_')}`] = buffer;
}
} catch (error) {
Sentry.captureException(error);
return;
}
for (const { id, locale, username } of profiles) {
const cardId = ulid();
let key = `card/${locale}/${encodeURIComponent(username).replace(/'/g, '_')}-${cardId}.png`;
if (mode === 'dark') {
key = mode === 'dark' ? key.replace('.png', '-dark.png') : key;
}
console.log(`Uploading @${username} (${locale}, ${mode}) ${cardId}`);
const buffer = results[`${locale}/${username.replace(/\.+$/, '').replace(/[^A-Za-z0-9.-]/g, '_')}`];
if (buffer === undefined) {
console.error('Cannot find the proper buffer!');
continue;
}
await s3.putObject({
Key: key,
Body: buffer,
ContentType: 'image/png',
ACL: 'public-read',
...awsParams,
});
await db.get(`
UPDATE profiles
SET ${mode === 'dark' ? 'cardDark' : 'card'}='https://${awsParams.Bucket}.s3.${awsConfig.region}.amazonaws.com/${key}'
WHERE id='${id}'`);
}
};
(async (): Promise<void> => {
const db = await dbConnection();
while (true) {
for (const mode of modes) {
await sleep(3000);
console.log(`Starting mode: ${mode}`);
await shoot(db, mode);
}
}
})();