Add printable guest sign studio and refine event imagery

This commit is contained in:
2026-09-10 09:26:49 -04:00
parent 176b5fa95c
commit 3a115f1161
48 changed files with 1294 additions and 102 deletions
+10 -30
View File
@@ -1,6 +1,8 @@
import { sql } from "drizzle-orm";
import { and, eq } from "drizzle-orm";
import sharp from "sharp";
import { bannerVariant, photoVariants, VARIANT_CONTENT_TYPE } from "./image-variants";
import type { BannerCrop } from "@album/contracts";
import { processPhotoExport } from "./exports";
import { processEmailDelivery } from "@album/email/queue";
import convert from "heic-convert";
@@ -84,31 +86,10 @@ async function processJob(job: ClaimedJob) {
const metadata = await image.metadata();
const displayKey = displayObjectKey(photo.eventId, photo.id);
const thumbKey = thumbObjectKey(photo.eventId, photo.id);
const [display, thumb] = await Promise.all([
image
.clone()
.resize({
width: 2048,
height: 2048,
fit: "inside",
withoutEnlargement: true,
})
.jpeg({ quality: 82, mozjpeg: true })
.toBuffer(),
image
.clone()
.resize({
width: 400,
height: 400,
fit: "inside",
withoutEnlargement: true,
})
.jpeg({ quality: 75, mozjpeg: true })
.toBuffer(),
]);
const [display, thumb] = await photoVariants(image);
await Promise.all([
putObject({ key: displayKey, body: display, contentType: "image/jpeg" }),
putObject({ key: thumbKey, body: thumb, contentType: "image/jpeg" }),
putObject({ key: displayKey, body: display, contentType: VARIANT_CONTENT_TYPE }),
putObject({ key: thumbKey, body: thumb, contentType: VARIANT_CONTENT_TYPE }),
]);
await db.transaction(async (tx) => {
await tx
@@ -176,18 +157,17 @@ async function processBanner() {
SELECT id FROM event_banners
WHERE status = 'pending' OR (status = 'processing' AND updated_at < now() - interval '10 minutes')
ORDER BY created_at FOR UPDATE SKIP LOCKED LIMIT 1
) RETURNING id, event_id, original_key, content_type
) RETURNING id, event_id, original_key, content_type, crop
`);
const banner = (rows as unknown as { id: string; event_id: string; original_key: string; content_type: string }[])[0];
const banner = (rows as unknown as { id: string; event_id: string; original_key: string; content_type: string; crop: BannerCrop | null }[])[0];
if (!banner) return false;
const scope = and(eq(eventBanners.id, banner.id), eq(eventBanners.eventId, banner.event_id));
try {
const original = await getObjectBuffer(banner.original_key);
const image = await decodeImage(original, banner.content_type);
const display = await image.resize({ width: 2400, height: 2400, fit: "inside", withoutEnlargement: true })
.jpeg({ quality: 82, mozjpeg: true }).toBuffer();
const displayKey = `events/${banner.event_id}/banners/${banner.id}/display.jpg`;
await putObject({ key: displayKey, body: display, contentType: "image/jpeg" });
const display = await bannerVariant(image, banner.crop);
const displayKey = `events/${banner.event_id}/banners/${banner.id}/display.webp`;
await putObject({ key: displayKey, body: display, contentType: VARIANT_CONTENT_TYPE });
await getDb().update(eventBanners).set({ status: "ready", displayKey, updatedAt: new Date() }).where(scope);
console.info(`Banner processed for event ${banner.event_id}`);
} catch {