365 lines
11 KiB
TypeScript
365 lines
11 KiB
TypeScript
import {
|
|
createPostTextSchema,
|
|
createPostImageSchema,
|
|
createPostLinkSchema,
|
|
} from "$lib/schemas";
|
|
import { validateData } from "$lib/utils";
|
|
import { error, fail, redirect } from "@sveltejs/kit";
|
|
import { serialize } from "object-to-formdata";
|
|
import { marked } from "marked";
|
|
|
|
import got from "got";
|
|
import cheerio from "cheerio";
|
|
import * as blobUtil from "blob-util"; // Changed import
|
|
import sharp from "sharp";
|
|
|
|
function removeDuplicateClasses(str) {
|
|
return str.replace(
|
|
/class="([^"]*)"/,
|
|
(match, classAttr) =>
|
|
`class="${[...new Set(classAttr.split(" "))].join(" ")}"`
|
|
);
|
|
}
|
|
|
|
function addClassesToHtml(htmlString) {
|
|
// Helper function to add a class to a specific tag
|
|
function addClassToTag(tag, className) {
|
|
// Add class if the tag doesn't already have a class attribute
|
|
const regex = new RegExp(`<${tag}(?![^>]*\\bclass=)([^>]*)>`, "g");
|
|
htmlString = htmlString.replace(regex, `<${tag} class="${className}"$1>`);
|
|
|
|
// Append the new class to tags that already have a class attribute, ensuring no duplicates
|
|
const regexWithClass = new RegExp(
|
|
`(<${tag}[^>]*\\bclass=["'][^"']*)(?!.*\\b${className}\\b)([^"']*)["']`,
|
|
"g"
|
|
);
|
|
htmlString = htmlString.replace(regexWithClass, `$1 ${className}$2"`);
|
|
}
|
|
|
|
// Add classes to headings
|
|
addClassToTag("h1", "text-lg");
|
|
addClassToTag("h2", "text-lg");
|
|
addClassToTag("h3", "text-lg");
|
|
addClassToTag("h4", "text-lg");
|
|
addClassToTag("h5", "text-lg");
|
|
addClassToTag("h6", "text-lg");
|
|
|
|
// Add classes to anchor tags
|
|
addClassToTag("a", "text-blue-400 hover:text-white underline");
|
|
|
|
// Add classes to ordered lists
|
|
addClassToTag("ol", "list-decimal ml-10 text-sm");
|
|
|
|
// Add classes to unordered lists
|
|
addClassToTag("ul", "list-disc ml-10 text-sm -mt-5");
|
|
|
|
// Add classes to blockquotes and their paragraphs
|
|
function addClassToBlockquote() {
|
|
// Add class to blockquote
|
|
htmlString = htmlString.replace(
|
|
/<blockquote/g,
|
|
'<blockquote class="pl-4 pr-4 rounded-lg bg-[#323232]"'
|
|
);
|
|
|
|
// Add class to p inside blockquote
|
|
htmlString = htmlString.replace(
|
|
/<blockquote([^>]*)>\s*<p/g,
|
|
`<blockquote$1>\n<p class="text-sm font-medium leading-relaxed text-white"`
|
|
);
|
|
}
|
|
|
|
addClassToBlockquote();
|
|
|
|
// Remove duplicate classes after all modifications
|
|
htmlString = removeDuplicateClasses(htmlString);
|
|
|
|
return htmlString;
|
|
}
|
|
|
|
export const load = async ({ locals }) => {
|
|
if (!locals.pb.authStore.isValid) {
|
|
redirect(303, "/login");
|
|
}
|
|
};
|
|
|
|
export const actions = {
|
|
createPostText: async ({ request, locals }) => {
|
|
let newPost = "";
|
|
const body = await request.formData();
|
|
body.delete("thumbnail");
|
|
body.append("user", locals?.user?.id);
|
|
|
|
let { formData, errors } = await validateData(body, createPostTextSchema);
|
|
|
|
formData.description = addClassesToHtml(marked(formData?.description));
|
|
|
|
formData.tagTopic = JSON.parse(formData.tagTopic)[0];
|
|
formData.upvote = 1;
|
|
|
|
if (errors) {
|
|
return fail(400, {
|
|
data: formData,
|
|
errors: errors.fieldErrors,
|
|
});
|
|
}
|
|
|
|
//Each post gives the user +1 Karma points
|
|
await locals.pb.collection("users").update(locals.user.id, {
|
|
"karma+": 1,
|
|
});
|
|
|
|
try {
|
|
newPost = await locals.pb.collection("posts").create(serialize(formData));
|
|
|
|
// add the tagTopic manually because serialize does not work on arrays
|
|
await locals?.pb.collection("posts").update(newPost.id, {
|
|
tagTopic: formData.tagTopic,
|
|
});
|
|
|
|
//Save it collection alreadyVoted to keep track if user voted or not
|
|
//FormData for alreadyVoted
|
|
|
|
let formDataAlreadyVoted = new FormData();
|
|
formDataAlreadyVoted.append("post", newPost?.id);
|
|
formDataAlreadyVoted.append("user", newPost?.user);
|
|
formDataAlreadyVoted.append("type", "upvote");
|
|
//console.log(formDataAlreadyVoted)
|
|
await locals.pb.collection("alreadyVoted").create(formDataAlreadyVoted);
|
|
} catch (err) {
|
|
console.log("Error: ", err);
|
|
error(err.status, err.message);
|
|
}
|
|
|
|
if (newPost?.id?.length !== 0) {
|
|
redirect(303, "/community/post/" + newPost?.id);
|
|
} else {
|
|
redirect(303, "/community");
|
|
}
|
|
},
|
|
|
|
createPostImage: async ({ request, locals }) => {
|
|
let newPost = "";
|
|
const body = await request.formData();
|
|
const thumb = body.get("thumbnail");
|
|
|
|
if (thumb?.size === 0) {
|
|
body.delete("thumbnail");
|
|
}
|
|
|
|
body.append("user", locals?.user?.id);
|
|
|
|
let { formData, errors } = await validateData(body, createPostImageSchema);
|
|
|
|
formData.tagTopic = JSON.parse(formData.tagTopic)[0];
|
|
formData.upvote = 1;
|
|
|
|
if (errors) {
|
|
return fail(400, {
|
|
data: formData,
|
|
errors: errors.fieldErrors,
|
|
});
|
|
}
|
|
|
|
//Each post gives the user +1 Karma points
|
|
await locals.pb.collection("users").update(locals?.user?.id, {
|
|
"karma+": 1,
|
|
});
|
|
|
|
if (formData.thumbnail.type.includes("image")) {
|
|
try {
|
|
const image = formData.thumbnail;
|
|
const imageBuffer = await image.arrayBuffer();
|
|
const imageBufferArray = new Uint8Array(imageBuffer);
|
|
let optimizedImageBuffer;
|
|
|
|
if (image.type === "image/gif") {
|
|
// Process GIF files differently
|
|
optimizedImageBuffer = imageBufferArray;
|
|
} else {
|
|
// Process other image formats (e.g., JPEG, PNG) using sharp library
|
|
optimizedImageBuffer = await sharp(imageBufferArray)
|
|
.resize({
|
|
width: 800,
|
|
height: 1000,
|
|
fit: sharp.fit.inside,
|
|
withoutEnlargement: true,
|
|
})
|
|
.jpeg({ quality: 80 })
|
|
.toBuffer();
|
|
}
|
|
|
|
formData.thumbnail = new File([optimizedImageBuffer], image.name, {
|
|
type: image.type,
|
|
lastModified: image.lastModified,
|
|
});
|
|
} catch (err) {
|
|
console.log("Error:", err);
|
|
error(err.status, err.message);
|
|
}
|
|
}
|
|
|
|
try {
|
|
newPost = await locals.pb.collection("posts").create(serialize(formData));
|
|
|
|
// add the tagTopic manually because serialize does not work on arrays
|
|
await locals?.pb.collection("posts").update(newPost.id, {
|
|
tagTopic: formData?.tagTopic,
|
|
});
|
|
|
|
//Save it collection alreadyVoted to keep track if user voted or not
|
|
//FormData for alreadyVoted
|
|
|
|
let formDataAlreadyVoted = new FormData();
|
|
formDataAlreadyVoted.append("post", newPost.id);
|
|
formDataAlreadyVoted.append("user", newPost.user);
|
|
formDataAlreadyVoted.append("type", "upvote");
|
|
//console.log(formDataAlreadyVoted)
|
|
await locals.pb.collection("alreadyVoted").create(formDataAlreadyVoted);
|
|
} catch (err) {
|
|
console.log("Error: ", err);
|
|
error(err.status, err.message);
|
|
}
|
|
|
|
if (newPost?.id?.length !== 0) {
|
|
redirect(303, "/community/post/" + newPost?.id);
|
|
} else {
|
|
redirect(303, "/community");
|
|
}
|
|
},
|
|
|
|
createPostLink: async ({ request, locals }) => {
|
|
let newPost = "";
|
|
const body = await request.formData();
|
|
const url = body.get("link");
|
|
let image;
|
|
let description;
|
|
let imageBlob;
|
|
|
|
try {
|
|
const response = await got(url, {
|
|
headers: {
|
|
"user-agent":
|
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
|
|
},
|
|
responseType: "buffer",
|
|
});
|
|
|
|
const $ = cheerio.load(response.body);
|
|
//const title = $('head title').text();
|
|
description = $('head meta[property="og:description"]').attr("content");
|
|
image = $('head meta[property="og:image"]').attr("content");
|
|
|
|
if (!image) {
|
|
let largestSize = 0;
|
|
let largestImage = "";
|
|
$("img").each(async function () {
|
|
if (
|
|
$(this).attr("src") &&
|
|
$(this)
|
|
.attr("src")
|
|
.match(/\.(webp|jpg|jpeg|png|gif)$/)
|
|
) {
|
|
try {
|
|
const imageBuffer = await got(image, {
|
|
headers: {
|
|
"user-agent":
|
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
|
|
},
|
|
responseType: "buffer",
|
|
}).then((response) => response.body);
|
|
imageBlob = await blobUtil.createBlob([imageBuffer], {
|
|
// Changed usage
|
|
type: "image/jpeg",
|
|
});
|
|
} catch (error) {
|
|
// Handle the error when getting the image
|
|
console.error("Error getting image:", error);
|
|
}
|
|
}
|
|
});
|
|
image = largestImage;
|
|
}
|
|
|
|
// Download the image and append it to the form data
|
|
const imageBuffer = await got(image, {
|
|
headers: {
|
|
"user-agent":
|
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
|
|
},
|
|
responseType: "buffer",
|
|
}).then((response) => response.body);
|
|
imageBlob = await blobUtil.createBlob([imageBuffer], {
|
|
// Changed usage
|
|
type: "image/jpeg",
|
|
});
|
|
} catch (e) {
|
|
console.log(e);
|
|
}
|
|
|
|
//body.delete('thumbnail')
|
|
//body.append('thumbnail', imageBlob);
|
|
|
|
// Append the title to the form data
|
|
//body.append('name', title);
|
|
body.append("user", locals.user.id);
|
|
body.append("description", description);
|
|
|
|
/*
|
|
const thumb = body.get('thumbnail');
|
|
|
|
if (thumb.size === 0) {
|
|
body.delete('thumbnail');
|
|
}
|
|
*/
|
|
|
|
let { formData, errors } = await validateData(body, createPostLinkSchema);
|
|
|
|
formData.tagTopic = JSON.parse(formData.tagTopic)[0];
|
|
formData.upvote = 1;
|
|
|
|
if (imageBlob?.length !== 0) {
|
|
formData.thumbnail = imageBlob;
|
|
}
|
|
|
|
if (errors) {
|
|
return fail(400, {
|
|
data: formData,
|
|
errors: errors.fieldErrors,
|
|
});
|
|
}
|
|
|
|
//Each post gives the user +1 Karma points
|
|
await locals.pb.collection("users").update(locals?.user?.id, {
|
|
"karma+": 1,
|
|
});
|
|
|
|
try {
|
|
newPost = await locals.pb.collection("posts").create(serialize(formData));
|
|
|
|
// add the tagTopic manually because serialize does not work on arrays
|
|
await locals.pb.collection("posts").update(newPost.id, {
|
|
tagTopic: formData.tagTopic,
|
|
});
|
|
|
|
//Save it collection alreadyVoted to keep track if user voted or not
|
|
//FormData for alreadyVoted
|
|
|
|
let formDataAlreadyVoted = new FormData();
|
|
formDataAlreadyVoted.append("post", newPost.id);
|
|
formDataAlreadyVoted.append("user", newPost.user);
|
|
formDataAlreadyVoted.append("type", "upvote");
|
|
//console.log(formDataAlreadyVoted)
|
|
await locals.pb.collection("alreadyVoted").create(formDataAlreadyVoted);
|
|
} catch (err) {
|
|
console.log("Error: ", err);
|
|
error(err.status, err.message);
|
|
}
|
|
|
|
if (newPost?.id?.length !== 0) {
|
|
redirect(303, "/community/post/" + newPost?.id);
|
|
} else {
|
|
redirect(303, "/community");
|
|
}
|
|
},
|
|
};
|