local proxy for og images

This commit is contained in:
Chris W 2023-10-08 16:34:26 -06:00
parent 793292d0ed
commit c2945e9fb2
4 changed files with 60 additions and 2 deletions

View File

@ -4,9 +4,13 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/images/favicon.ico" /> <link rel="icon" href="%sveltekit.assets%/images/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#111721" />
<meta name="description" content="Paste69 is a free to use, open source pastebin featuring an api, syntax highlighting, encrypted pastes, and burn after reading." />
<meta name="keywords" content="paste69, paste, pastebin, 0x45, hastebin, code, text, encrypt, decrypt, burn after reading, open source, api, syntax highlighting" />
<meta name="author" content="Chris Watson" />
%sveltekit.head% %sveltekit.head%
</head> </head>
<body class="w-full h-full min-h-full" data-sveltekit-preload-data="hover" data-theme="skeleton"> <body class="w-full h-full" data-sveltekit-preload-data="hover" data-theme="skeleton">
<div style="display: contents">%sveltekit.body%</div> <div style="display: contents">%sveltekit.body%</div>
</body> </body>
</html> </html>

View File

@ -1,6 +1,7 @@
import { error } from '@sveltejs/kit'; import { error } from '@sveltejs/kit';
import type { PageLoad } from './$types'; import type { PageLoad } from './$types';
import { pastes } from '$db/index'; import { pastes } from '$db/index';
import { SITE_URL } from '$env/static/private';
export const load: PageLoad = async ({ params }) => { export const load: PageLoad = async ({ params }) => {
const [id, ext] = params.slug.split('.'); const [id, ext] = params.slug.split('.');
@ -14,6 +15,7 @@ export const load: PageLoad = async ({ params }) => {
// Build the response object // Build the response object
const response = { const response = {
id: paste.id, id: paste.id,
url: `${SITE_URL}/${id}.${paste.highlight}`,
contents: paste.contents, contents: paste.contents,
encrypted: paste.encrypted, encrypted: paste.encrypted,
highlight: ext || paste.highlight, highlight: ext || paste.highlight,

View File

@ -82,13 +82,19 @@
<svelte:head> <svelte:head>
<title>Paste69 - Paste {data.id}</title> <title>Paste69 - Paste {data.id}</title>
<meta name="description" content="Paste69 - Paste {data.id}" />
<meta property="og:title" content="Paste69 - Paste {data.id}" />
<meta property="og:description" content="Paste69 - Paste {data.id}" />
<meta property="og:image" content="/images/paste/{data.id}" />
<meta property="og:url" content={data.url} />
<meta property="og:type" content="website" />
</svelte:head> </svelte:head>
{#if renderMarkdown} {#if renderMarkdown}
<!-- prettier-ignore --> <!-- prettier-ignore -->
<div class="markdown text-xl max-w-[90ch] pb-24">{@html contents}</div> <div class="markdown text-xl max-w-[90ch] pb-24">{@html contents}</div>
{:else} {:else}
<pre class="pl-2 pt-5 pb-24 max-w-full break-words whitespace-pre-line" bind:this={codeRef} on:dblclick={() => selectAll()} ><code>{@html contents}</code></pre> <pre class="pl-2 pt-5 pb-24 min-h-full max-w-full break-words whitespace-pre-line overflow-x-auto" bind:this={codeRef} on:dblclick={() => selectAll()} ><code>{@html contents}</code></pre>
{/if} {/if}
<div class="fixed bottom-0 right-0 w-full md:w-auto"> <div class="fixed bottom-0 right-0 w-full md:w-auto">

View File

@ -0,0 +1,46 @@
import { pastes } from "$db/index";
import { SITE_URL } from "$env/static/private";
import { error, type RequestHandler } from "@sveltejs/kit";
export const GET: RequestHandler = async ({ params }) => {
const { id } = params;
const paste = await pastes.findOne({ id });
if (!paste) {
throw error(404, 'Paste not found');
}
if (paste.encrypted) {
throw error(404, 'Cannot generate image for encrypted paste');
}
if (paste.burnAfterReading) {
throw error(404, 'Cannot generate image for burnable paste');
}
const code = paste.contents;
// Grab at most 15 lines of the paste, if there aren't 15 lines, pad the rest with empty strings.
let lines = code.split('\n').slice(0, 15).concat(Array.from({ length: 15 - code.split('\n').length }, () => ''));
// Truncate each line to 80 characters, and pad the rest with spaces.
lines = lines.map(line => line.slice(0, 70).padEnd(70, ' '));
const title = `${SITE_URL}/${id}.${paste.highlight}`;
const url = `https://inkify.0x45.st/generate?code=${encodeURIComponent(lines.join('\n'))}&window_title=${encodeURIComponent(title)}&language=${encodeURIComponent(paste.highlight)}&pad_horiz=5&pad_vert=5`;
const res = await fetch(url);
const image = res.body;
if (image) {
return new Response(image, {
headers: {
'Content-Type': 'image/png',
'Cache-Control': 'public, max-age=604800, immutable',
},
});
} else {
throw error(500, 'Could not generate image');
}
};