feat: add some shit
This commit is contained in:
parent
3dc9692eef
commit
32b6b04eb9
21
lib/cache/image.ts
vendored
21
lib/cache/image.ts
vendored
@ -1,5 +1,6 @@
|
|||||||
import { hash } from "@lib/hash.ts";
|
import { hash } from "@lib/hash.ts";
|
||||||
import * as cache from "@lib/cache/cache.ts";
|
import * as cache from "@lib/cache/cache.ts";
|
||||||
|
import { ImageMagick } from "https://deno.land/x/imagemagick_deno@0.0.25/mod.ts";
|
||||||
|
|
||||||
type ImageCacheOptions = {
|
type ImageCacheOptions = {
|
||||||
url: string;
|
url: string;
|
||||||
@ -19,6 +20,20 @@ function getCacheKey({ url: _url, width, height }: ImageCacheOptions) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function verifyImage(
|
||||||
|
imageBuffer: Uint8Array,
|
||||||
|
) {
|
||||||
|
return new Promise<boolean>((resolve) => {
|
||||||
|
try {
|
||||||
|
ImageMagick.read(imageBuffer, (image) => {
|
||||||
|
resolve(image.height !== 0 && image.width !== 0);
|
||||||
|
});
|
||||||
|
} catch (_err) {
|
||||||
|
resolve(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export async function getImage({ url, width, height }: ImageCacheOptions) {
|
export async function getImage({ url, width, height }: ImageCacheOptions) {
|
||||||
const cacheKey = getCacheKey({ url, width, height });
|
const cacheKey = getCacheKey({ url, width, height });
|
||||||
|
|
||||||
@ -44,6 +59,12 @@ export async function setImage(
|
|||||||
) {
|
) {
|
||||||
const clone = new Uint8Array(buffer);
|
const clone = new Uint8Array(buffer);
|
||||||
|
|
||||||
|
const imageCorrect = await verifyImage(clone);
|
||||||
|
if (!imageCorrect) {
|
||||||
|
console.log("[cache/image] failed to store image", { url });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const cacheKey = getCacheKey({ url, width, height });
|
const cacheKey = getCacheKey({ url, width, height });
|
||||||
const pointerId = await hash(cacheKey);
|
const pointerId = await hash(cacheKey);
|
||||||
|
|
||||||
|
@ -2,8 +2,10 @@ import { HandlerContext, Handlers } from "$fresh/server.ts";
|
|||||||
import {
|
import {
|
||||||
ImageMagick,
|
ImageMagick,
|
||||||
initialize,
|
initialize,
|
||||||
|
MagickFormat,
|
||||||
MagickGeometry,
|
MagickGeometry,
|
||||||
} from "https://deno.land/x/imagemagick_deno@0.0.25/mod.ts";
|
} from "https://deno.land/x/imagemagick_deno@0.0.25/mod.ts";
|
||||||
|
|
||||||
import { parseMediaType } from "https://deno.land/std@0.175.0/media_types/parse_media_type.ts";
|
import { parseMediaType } from "https://deno.land/std@0.175.0/media_types/parse_media_type.ts";
|
||||||
import * as cache from "@lib/cache/image.ts";
|
import * as cache from "@lib/cache/image.ts";
|
||||||
import { SILVERBULLET_SERVER } from "@lib/env.ts";
|
import { SILVERBULLET_SERVER } from "@lib/env.ts";
|
||||||
@ -49,10 +51,21 @@ function getWidthHeight(
|
|||||||
|
|
||||||
function modifyImage(
|
function modifyImage(
|
||||||
imageBuffer: Uint8Array,
|
imageBuffer: Uint8Array,
|
||||||
params: { width: number; height: number; mode: "resize" | "crop" },
|
params: {
|
||||||
|
width: number;
|
||||||
|
mediaType: string;
|
||||||
|
height: number;
|
||||||
|
mode: "resize" | "crop";
|
||||||
|
},
|
||||||
) {
|
) {
|
||||||
return new Promise<Uint8Array>((resolve) => {
|
return new Promise<Uint8Array>((resolve) => {
|
||||||
ImageMagick.read(imageBuffer, (image) => {
|
let format = MagickFormat.Jpeg;
|
||||||
|
|
||||||
|
if (params.mediaType === "image/webp") {
|
||||||
|
format = MagickFormat.Webp;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageMagick.read(imageBuffer, format, (image) => {
|
||||||
const sizingData = getWidthHeight(image, params);
|
const sizingData = getWidthHeight(image, params);
|
||||||
if (params.mode === "resize") {
|
if (params.mode === "resize") {
|
||||||
image.resize(sizingData);
|
image.resize(sizingData);
|
||||||
@ -100,6 +113,7 @@ async function processImage(imageUrl: string, params: ImageParams) {
|
|||||||
|
|
||||||
const modifiedImage = await modifyImage(remoteImage.buffer, {
|
const modifiedImage = await modifyImage(remoteImage.buffer, {
|
||||||
...params,
|
...params,
|
||||||
|
mediaType: remoteImage.mediaType,
|
||||||
mode: "resize",
|
mode: "resize",
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -108,13 +122,6 @@ async function processImage(imageUrl: string, params: ImageParams) {
|
|||||||
length: modifiedImage.length,
|
length: modifiedImage.length,
|
||||||
});
|
});
|
||||||
|
|
||||||
await cache.setImage(modifiedImage.slice(), {
|
|
||||||
url: imageUrl,
|
|
||||||
width: params.width,
|
|
||||||
height: params.height,
|
|
||||||
mediaType: remoteImage.mediaType,
|
|
||||||
});
|
|
||||||
|
|
||||||
return [modifiedImage, remoteImage.mediaType] as const;
|
return [modifiedImage, remoteImage.mediaType] as const;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,15 +138,13 @@ const GET = async (
|
|||||||
|
|
||||||
const imageUrl = SILVERBULLET_SERVER + "/" + params.image;
|
const imageUrl = SILVERBULLET_SERVER + "/" + params.image;
|
||||||
|
|
||||||
console.log("[api/image] " + imageUrl);
|
|
||||||
|
|
||||||
const cachedResponse = await cache.getImage({
|
const cachedResponse = await cache.getImage({
|
||||||
url: imageUrl,
|
url: imageUrl,
|
||||||
width: params.width,
|
width: params.width,
|
||||||
height: params.height,
|
height: params.height,
|
||||||
});
|
});
|
||||||
if (cachedResponse) {
|
if (cachedResponse) {
|
||||||
console.log("[api/image] got cached image");
|
console.log("[api/image] cached: " + imageUrl);
|
||||||
return new Response(cachedResponse.buffer.slice(), {
|
return new Response(cachedResponse.buffer.slice(), {
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": cachedResponse.mediaType,
|
"Content-Type": cachedResponse.mediaType,
|
||||||
@ -153,6 +158,15 @@ const GET = async (
|
|||||||
processImage(imageUrl, params)
|
processImage(imageUrl, params)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
cache.setImage(resizedImage.slice(), {
|
||||||
|
url: imageUrl,
|
||||||
|
width: params.width,
|
||||||
|
height: params.height,
|
||||||
|
mediaType: mediaType,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("[api/image] not-cached: " + imageUrl);
|
||||||
|
|
||||||
return new Response(resizedImage, {
|
return new Response(resizedImage, {
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": mediaType,
|
"Content-Type": mediaType,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user