webpages can now be a image or pdf

This commit is contained in:
daniel31x13
2023-11-25 03:19:02 -05:00
parent 676c7c3a5d
commit b88fa446be
12 changed files with 156 additions and 15 deletions
+35 -4
View File
@@ -1,17 +1,20 @@
import { prisma } from "@/lib/api/db";
import { LinkIncludingShortenedCollectionAndTags } from "@/types/global";
import getTitle from "@/lib/api/getTitle";
import archive from "@/lib/api/archive";
import urlHandler from "@/lib/api/urlHandler";
import { UsersAndCollections } from "@prisma/client";
import getPermission from "@/lib/api/getPermission";
import createFolder from "@/lib/api/storage/createFolder";
import pdfHandler from "../../pdfHandler";
import validateUrlSize from "../../validateUrlSize";
import imageHandler from "../../imageHandler";
export default async function postLink(
link: LinkIncludingShortenedCollectionAndTags,
userId: number
) {
try {
new URL(link.url);
if (link.url) new URL(link.url);
} catch (error) {
return {
response:
@@ -45,13 +48,33 @@ export default async function postLink(
const description =
link.description && link.description !== ""
? link.description
: await getTitle(link.url);
: link.url
? await getTitle(link.url)
: undefined;
const validatedUrl = link.url ? await validateUrlSize(link.url) : undefined;
if (validatedUrl === null)
return { response: "File is too large to be stored.", status: 400 };
const contentType = validatedUrl?.get("content-type");
let linkType = "url";
let imageExtension = "png";
if (!link.url) linkType = link.type;
else if (contentType === "application/pdf") linkType = "pdf";
else if (contentType?.startsWith("image")) {
linkType = "image";
if (contentType === "image/jpeg") imageExtension = "jpeg";
else if (contentType === "image/png") imageExtension = "png";
}
const newLink = await prisma.link.create({
data: {
url: link.url,
name: link.name,
description,
type: linkType,
readabilityPath: "pending",
collection: {
connectOrCreate: {
@@ -91,7 +114,15 @@ export default async function postLink(
createFolder({ filePath: `archives/${newLink.collectionId}` });
archive(newLink.id, newLink.url, userId);
newLink.url && linkType === "url"
? urlHandler(newLink.id, newLink.url, userId)
: undefined;
linkType === "pdf" ? pdfHandler(newLink.id, newLink.url) : undefined;
linkType === "image"
? imageHandler(newLink.id, newLink.url, imageExtension)
: undefined;
return { response: newLink, status: 200 };
}
+37
View File
@@ -0,0 +1,37 @@
import { prisma } from "@/lib/api/db";
import createFile from "@/lib/api/storage/createFile";
import fs from "fs";
import path from "path";
export default async function imageHandler(
linkId: number,
url: string | null,
extension: string,
file?: string
) {
const pdf = await fetch(url as string).then((res) => res.blob());
const buffer = Buffer.from(await pdf.arrayBuffer());
const linkExists = await prisma.link.findUnique({
where: { id: linkId },
});
linkExists
? await createFile({
data: buffer,
filePath: `archives/${linkExists.collectionId}/${linkId}.${extension}`,
})
: undefined;
await prisma.link.update({
where: { id: linkId },
data: {
screenshotPath: linkExists
? `archives/${linkExists.collectionId}/${linkId}.${extension}`
: null,
pdfPath: null,
readabilityPath: null,
},
});
}
+44
View File
@@ -0,0 +1,44 @@
import { prisma } from "@/lib/api/db";
import createFile from "@/lib/api/storage/createFile";
import fs from "fs";
import path from "path";
export default async function pdfHandler(
linkId: number,
url: string | null,
file?: string
) {
const targetLink = await prisma.link.update({
where: { id: linkId },
data: {
pdfPath: "pending",
lastPreserved: new Date().toISOString(),
},
});
const pdf = await fetch(url as string).then((res) => res.blob());
const buffer = Buffer.from(await pdf.arrayBuffer());
const linkExists = await prisma.link.findUnique({
where: { id: linkId },
});
linkExists
? await createFile({
data: buffer,
filePath: `archives/${linkExists.collectionId}/${linkId}.pdf`,
})
: undefined;
await prisma.link.update({
where: { id: linkId },
data: {
pdfPath: linkExists
? `archives/${linkExists.collectionId}/${linkId}.pdf`
: null,
readabilityPath: null,
screenshotPath: null,
},
});
}
+1 -1
View File
@@ -97,7 +97,7 @@ export default async function readFile(filePath: string) {
return {
file: "File not found.",
contentType: "text/plain",
status: 400,
status: 404,
};
else {
const file = fs.readFileSync(creationPath);
+1 -1
View File
@@ -6,7 +6,7 @@ import { Readability } from "@mozilla/readability";
import { JSDOM } from "jsdom";
import DOMPurify from "dompurify";
export default async function archive(
export default async function urlHandler(
linkId: number,
url: string,
userId: number
+13
View File
@@ -0,0 +1,13 @@
export default async function validateUrlSize(url: string) {
try {
const response = await fetch(url, { method: "HEAD" });
const totalSizeMB =
Number(response.headers.get("content-length")) / Math.pow(1024, 2);
if (totalSizeMB > 50) return null;
else return response.headers;
} catch (err) {
console.log(err);
return null;
}
}