Monorepo for Aesthetic.Computer
aesthetic.computer
1// Generates an image thumbnail of the starting screen of a piece.
2// See also: `/thumbnail-server` for an alternate implementation.
3
4// Fastify docs: https://www.fastify.io/docs/latest/Guides/Getting-Started
5
6// https://aesthetic.computer/thumbnail/widthxheight/command~any~params.jpg
7
8import Fastify from 'fastify'
9
10const fastify = Fastify({
11 logger: true
12})
13
14import { chromium } from 'playwright';
15const acceptedResolutions = ["1200x630", "1800x900"]; // og:image, twitter:image
16
17fastify.get('/thumbnail/:resolution/:command.jpg', async (request, reply) => {
18
19 const { resolution, command } = request.params;
20
21 // Parse "IntxInt" to get the correct resolution to take a screenshot by.
22 const [width, height] = resolution.split("x").map((n) => parseInt(n));
23
24 // Ditch if we don't hit the accepted resolution whitelist.
25 if (acceptedResolutions.indexOf(resolution) === -1) {
26 reply.code(500);
27 reply.send("error");
28 }
29
30 // Option 2: Playwright
31 const browser = await chromium.launch({ channel: "chrome" });
32
33 const context = await browser.newContext({
34 viewport: {
35 width: Math.ceil(width / 2),
36 height: Math.ceil(height / 2),
37 },
38 deviceScaleFactor: 2,
39 });
40
41 const page = await context.newPage();
42
43 page.on("console", (message) => {
44 console.log(message.text());
45 });
46
47 page.on("pageerror", (err) => {
48 console.log(err.message);
49 });
50
51 // TODO: Rewrite the URL below so that I can test locally without hitting
52 // aesthetic.computer's production deployment. 22.07.17.22.30
53 // - `https://${event.headers['x-forwarded-host']}/${command || ""}`
54
55 try {
56 await page.goto(`https://aesthetic.computer/${command || ""}`, {
57 waitUntil: "networkidle",
58 timeout: 3000
59 });
60 } catch {
61 console.log("Failed idle network...");
62 }
63
64 // Add a potential extra 2 seconds until preloading is ready.
65 try {
66 await page.waitForFunction(() => preloaded === true, {timeout: 3000});
67 } catch {
68 console.log("Failed preloaded check...");
69 }
70
71 console.log("Waiting for 1s...");
72 await page.waitForTimeout(1000); // A bit of extra time.
73
74 const buffer = await page.screenshot();
75
76 const buffer = await page.screenshot({
77 type: "jpeg",
78 quality: 80
79 });
80
81 await browser.close();
82
83 reply.headers({
84 "Content-Type": "image/jpeg",
85 "Content-Length": buffer.length.toString(),
86 });
87
88 reply.code(200);
89 reply.send(buffer);
90})
91
92const start = async () => {
93 try {
94 await fastify.listen({ port: 8081 })
95 } catch (err) {
96 fastify.log.error(err)
97 process.exit(1)
98 }
99}
100
101start();