import { Octokit } from "@octokit/rest";
import { Base64 } from "js-base64";
/**
* Converts a string to a URL-friendly slug.
* @param {string} text - The text to be slugified.
* @return {string} The slugified text.
*/
const slugify = (text) => {
return text
.toString()
.toLowerCase()
.trim()
.replace(/\s+/g, '-') // Replace spaces with -
.replace(/[^\w\-]+/g, '') // Remove all non-word chars
.replace(/\-\-+/g, '-') // Replace multiple - with single -
.replace(/^-+/, '') // Trim - from start of text
.replace(/-+$/, ''); // Trim - from end of text
};
/**
* Formats a date string to YYYY-MM-DD.
* @param {string} date - The date string to format.
* @return {string} The formatted date string.
*/
const formatDate = (date) => {
const d = new Date(date);
if (isNaN(d.getTime())) {
throw new Error('Invalid date provided');
}
return d.toISOString().split('T')[0];
};
/**
* Creates the content for a blog post.
* @param {Object} data - The data for the blog post.
* @param {string} data.by_nickname - The author's nickname.
* @param {string} data.by_email - The author's email.
* @param {string} data.content - The content of the post.
* @param {string} data.time - The timestamp of the post.
* @return {string} The formatted blog post content.
*/
const createPostContent = (data) => {
const { by_nickname, by_email, content, time } = data;
const slugName = slugify(by_nickname);
const date = formatDate(time);
return `---
tags:
- ${by_email}
info: aberto.
date: ${date}
type: post
layout: post
published: true
slug: ${slugName}
title: '${by_nickname}'
---
${content}`;
};
/**
* Handles the webhook event for creating a new blog post.
* @param {Object} event - The webhook event object.
* @return {Object} The response object.
*/
export const handleWebhook = async (event) => {
try {
if (!event || !event.detail || !event.detail.data) {
throw new Error('Invalid event structure');
}
const { by_nickname, by_email, content } = event.detail.data;
const time = event.time || new Date().toISOString();
if (!by_email || !by_nickname || !content) {
throw new Error('Missing required fields: email, nickname, or content');
}
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
if (!process.env.GITHUB_TOKEN) {
throw new Error('GitHub token is not set');
}
const owner = "${REPO_OWNER}";
const repo = "${REPO_NAME}";
const date = formatDate(time);
const slugName = slugify(by_nickname);
const path = `_posts/${date}-${slugName}.md`;
const message = `New post by ${by_nickname}`;
const postContent = createPostContent({ by_nickname, by_email, content, time });
const contentEncoded = Base64.encode(postContent);
await octokit.repos.createOrUpdateFileContents({
owner,
repo,
path,
message,
content: contentEncoded,
});
return {
statusCode: 200,
body: JSON.stringify({ message: "File created/updated successfully", path }),
};
} catch (error) {
console.error('Error in handleWebhook:', error);
return {
statusCode: error.status || 500,
body: JSON.stringify({ message: error.message || "An unexpected error occurred" }),
};
}
};