Monorepo for Aesthetic.Computer aesthetic.computer
at main 101 lines 2.7 kB view raw
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();