import { closeSync, constants, fstatSync, openSync, readFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { basename, dirname } from "node:path"; import { detectImageMimeType, type SupportedImageMimeType } from "./attachments.ts"; const PI_CLIPBOARD_FILE = /^pi-clipboard-[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\.(png|jpe?g|gif|webp)$/i; export const MAX_CLIPBOARD_IMAGE_BYTES = 20 * 1024 * 1024; export interface LoadedClipboardImage { path: string; bytes: Uint8Array; mimeType: SupportedImageMimeType; } export function isPiClipboardImagePath(value: string): boolean { return dirname(value) === tmpdir() && PI_CLIPBOARD_FILE.test(basename(value)); } export function loadPiClipboardImage(value: string): LoadedClipboardImage | undefined { if (!isPiClipboardImagePath(value)) return undefined; let fileDescriptor: number | undefined; try { const noFollow = "O_NOFOLLOW" in constants ? constants.O_NOFOLLOW : 0; fileDescriptor = openSync(value, constants.O_RDONLY | noFollow); const stat = fstatSync(fileDescriptor); if (!stat.isFile() || stat.size <= 0 || stat.size > MAX_CLIPBOARD_IMAGE_BYTES) { return undefined; } const bytes = new Uint8Array(readFileSync(fileDescriptor)); const mimeType = detectImageMimeType(bytes); if (!mimeType) return undefined; return { path: value, bytes, mimeType }; } catch { return undefined; } finally { if (fileDescriptor !== undefined) closeSync(fileDescriptor); } }