87 lines
2.4 KiB
TypeScript
87 lines
2.4 KiB
TypeScript
|
|
import { TRPCError } from "@trpc/server";
|
||
|
|
import puppeteer from "puppeteer-core";
|
||
|
|
import { env } from "~/env";
|
||
|
|
import type { AnnunciId } from "~/schemas/public/Annunci";
|
||
|
|
import { getKeydbClient } from "~/utils/keydb";
|
||
|
|
import { TOKEN_CONFIG } from "../auth/configs";
|
||
|
|
|
||
|
|
export const genPdfSchedaAnnuncioBase64 = async (annuncioId: AnnunciId) => {
|
||
|
|
const pdf = await genPdfSchedaAnnuncio(annuncioId);
|
||
|
|
const pdfBase64 = Buffer.from(pdf).toString("base64");
|
||
|
|
const base64Content = pdfBase64.includes("base64,")
|
||
|
|
? pdfBase64.split("base64,")[1]
|
||
|
|
: pdfBase64;
|
||
|
|
if (!base64Content) {
|
||
|
|
throw new Error("Failed to convert PDF to base64");
|
||
|
|
}
|
||
|
|
return base64Content;
|
||
|
|
};
|
||
|
|
|
||
|
|
export const genPdfSchedaAnnuncio = async (annuncioId: AnnunciId) => {
|
||
|
|
const keybd = getKeydbClient();
|
||
|
|
if (keybd) {
|
||
|
|
const cacheKey = `scheda-annuncio-${annuncioId}`;
|
||
|
|
const cached = await keybd.get(cacheKey);
|
||
|
|
if (cached) {
|
||
|
|
return new Uint8Array(Buffer.from(cached, "base64"));
|
||
|
|
}
|
||
|
|
const scheda = await puppeteerSchedaAnnuncio(annuncioId);
|
||
|
|
await keybd.set(
|
||
|
|
cacheKey,
|
||
|
|
Buffer.from(scheda).toString("base64"),
|
||
|
|
"EX",
|
||
|
|
3600 * 5,
|
||
|
|
);
|
||
|
|
return scheda;
|
||
|
|
}
|
||
|
|
return await puppeteerSchedaAnnuncio(annuncioId);
|
||
|
|
};
|
||
|
|
|
||
|
|
const puppeteerSchedaAnnuncio = async (annuncioId: AnnunciId) => {
|
||
|
|
let browser = null;
|
||
|
|
|
||
|
|
try {
|
||
|
|
browser = await puppeteer.connect({
|
||
|
|
browserWSEndpoint: env.BROWSER_WS_URL,
|
||
|
|
});
|
||
|
|
|
||
|
|
const page = await browser.newPage();
|
||
|
|
|
||
|
|
const productionDomain = new URL(env.INTERNAL_BASE_URL).hostname;
|
||
|
|
const newCookies = [
|
||
|
|
{
|
||
|
|
name: TOKEN_CONFIG.OVERRIDE_TOKEN_COOKIE_NAME,
|
||
|
|
value: env.EXP_API_PASS,
|
||
|
|
domain:
|
||
|
|
env.NODE_ENV === "production"
|
||
|
|
? productionDomain
|
||
|
|
: "host.docker.internal",
|
||
|
|
path: "/",
|
||
|
|
},
|
||
|
|
];
|
||
|
|
await browser.setCookie(...newCookies);
|
||
|
|
|
||
|
|
const baseUrl =
|
||
|
|
env.NODE_ENV === "production"
|
||
|
|
? env.INTERNAL_BASE_URL
|
||
|
|
: `http://host.docker.internal:3000`;
|
||
|
|
|
||
|
|
const targetUrl = `${baseUrl}/area-riservata/admin/scheda-annuncio-stampa/${annuncioId}?raw=true`;
|
||
|
|
await page.goto(targetUrl, { waitUntil: "networkidle0" });
|
||
|
|
|
||
|
|
const pdf = await page.pdf({
|
||
|
|
format: "A4",
|
||
|
|
printBackground: true,
|
||
|
|
});
|
||
|
|
return pdf;
|
||
|
|
} catch (error) {
|
||
|
|
throw new TRPCError({
|
||
|
|
code: "INTERNAL_SERVER_ERROR",
|
||
|
|
message: `Errore nella generazione del PDF: ${(error as Error).message}`,
|
||
|
|
});
|
||
|
|
} finally {
|
||
|
|
// 'disconnect' tells browserless you're done with this tab
|
||
|
|
if (browser) await browser.disconnect();
|
||
|
|
}
|
||
|
|
};
|