Skip to content

Commit

Permalink
Fix: Added stale time
Browse files Browse the repository at this point in the history
please :(
  • Loading branch information
AntGa committed Oct 21, 2024
1 parent d9fc69d commit b823fb5
Showing 1 changed file with 100 additions and 36 deletions.
136 changes: 100 additions & 36 deletions src/scripts/updateProjects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,32 @@ import sharp from "sharp";
import { supabase } from '../lib/supabaseClient';
import { supabaseUrl } from '../lib/supabaseClient';
import { prisma } from "../lib/prisma.ts";
import type { APIRoute } from 'astro';

// Function to sanitize filenames
function sanitizeFileName(fileName: string): string {
return fileName.replace(/[^a-z0-9-_.]/gi, '-'); // Replace invalid characters with hyphen
}

// Function to download image from URL
// Function to download image from URL with timeout and error handling
async function downloadImage(url: string): Promise<Buffer> {
const response = await axios.get(url, { responseType: 'arraybuffer' });
return Buffer.from(response.data, 'binary');
try {
const response = await axios.get(url, {
responseType: 'arraybuffer',
timeout: 10000, // Set a timeout of 10 seconds
});
return Buffer.from(response.data, 'binary');
} catch (error) {
throw new Error(`Failed to download image: ${(error as Error).message}`);
}
}

// Function to fetch fresh cover URL from Notion
async function getFreshCoverUrl(notion: Client, pageId: string): Promise<string> {
const page = await notion.pages.retrieve({ page_id: pageId }) as projectRow;
const coverUrl = page.cover?.type === "external"
? page.cover?.external.url
: page.cover?.file.url ?? "";
return coverUrl;
}

// Function to delete image from Supabase Storage
Expand All @@ -27,25 +42,31 @@ async function deleteImageFromSupabase(filePath: string): Promise<void> {
}
}

// Function to upload image to Supabase Storage
// Function to upload image to Supabase Storage with error handling
async function uploadImageToSupabase(imageBuffer: Buffer, filePath: string): Promise<string> {
// Convert image to WebP format and compress it
const compressedImageBuffer = await sharp(imageBuffer)
.toFormat('webp', { quality: 30 })
.toBuffer();
try {
// Convert image to WebP format and compress it
const compressedImageBuffer = await sharp(imageBuffer)
.toFormat('webp', { quality: 30 })
.toBuffer();

// Attempt to delete the existing image first
await deleteImageFromSupabase(filePath);
// Attempt to delete the existing image first
await deleteImageFromSupabase(filePath);

// Upload the new image to Supabase
const { data, error } = await supabase.storage.from('images').upload(filePath, compressedImageBuffer);
// Upload the new image to Supabase
const { data, error } = await supabase.storage
.from('images')
.upload(filePath, compressedImageBuffer);

if (error) {
throw new Error(`Failed to upload image: ${error.message}`);
}
if (error) {
throw new Error(`Failed to upload image: ${error.message}`);
}

// Return the public URL of the uploaded image
return `${supabaseUrl}/storage/v1/object/public/images/${filePath}`;
// Return the public URL of the uploaded image
return `${supabaseUrl}/storage/v1/object/public/images/${filePath}`;
} catch (error) {
throw new Error(`Failed to process and upload image: ${(error as Error).message}`);
}
}

// Function to log messages
Expand All @@ -62,11 +83,15 @@ function sendLog(controller: ReadableStreamDefaultController, message: string) {
}

// Update the updateProjects function
export async function updateProjects(controller: ReadableStreamDefaultController): Promise<void> {
export async function updateProjects(
controller: ReadableStreamDefaultController
): Promise<void> {
const NOTION_TOKEN = process.env.NOTION_TOKEN || import.meta.env.NOTION_TOKEN;
const NOTION_PROJECTS_ID = process.env.NOTION_PROJECTS_ID || import.meta.env.NOTION_PROJECTS_ID;
const NOTION_PROJECTS_ID =
process.env.NOTION_PROJECTS_ID || import.meta.env.NOTION_PROJECTS_ID;

if (!NOTION_TOKEN || !NOTION_PROJECTS_ID) {
sendLog(controller, "Missing Notion token or database ID.");
throw new Error("Missing secret(s)");
}

Expand All @@ -78,7 +103,7 @@ export async function updateProjects(controller: ReadableStreamDefaultController
// Step 1: Get all project IDs from Notion
const query = await notion.databases.query({
database_id: NOTION_PROJECTS_ID,
sorts: [{ property: 'Date', direction: 'descending' }]
sorts: [{ property: 'Date', direction: 'descending' }],
});
const projectsRows = query.results as projectRow[];

Expand All @@ -92,7 +117,9 @@ export async function updateProjects(controller: ReadableStreamDefaultController
const prismaProjectIds = prismaProjects.map(project => project.id);

// Step 3: Identify projects to delete (those in Prisma but not in Notion)
const projectsToDelete = prismaProjects.filter(project => !notionProjectIds.includes(project.id));
const projectsToDelete = prismaProjects.filter(
project => !notionProjectIds.includes(project.id)
);

// Step 4: Delete projects from Prisma and Supabase
for (const project of projectsToDelete) {
Expand All @@ -106,33 +133,67 @@ export async function updateProjects(controller: ReadableStreamDefaultController
where: { id: project.id },
});

sendLog(controller, `Deleted project ${project.id} from Prisma and its image from Supabase.`);
sendLog(
controller,
`Deleted project ${project.id} from Prisma and its image from Supabase.`
);
}

// Process the remaining projects (already in your existing logic)
// Process the remaining projects
const projectPromises = projectsRows.map(async (row) => {
const title = row.properties.Name.title[0] ? row.properties.Name.title[0].plain_text : "";
const dateStr = row.properties.Date.date ? row.properties.Date.date.start : "";
const title = row.properties.Name.title[0]
? row.properties.Name.title[0].plain_text
: "";
const dateStr = row.properties.Date.date
? row.properties.Date.date.start
: "";
const date = dateStr ? new Date(dateStr) : null; // Convert string to Date object
const description = row.properties.Description.rich_text[0] ? row.properties.Description.rich_text[0].plain_text : "";
const coverUrl = row.cover?.type === "external" ? row.cover?.external.url : row.cover?.file.url ?? "";
const team = row.properties.Team.rich_text[0] ? row.properties.Team.rich_text[0].plain_text : "";
const tags = row.properties.Tags?.multi_select.map((tag) => tag.name) || []; // Ensure tags is always an array
const description = row.properties.Description.rich_text[0]
? row.properties.Description.rich_text[0].plain_text
: "";
const team = row.properties.Team.rich_text[0]
? row.properties.Team.rich_text[0].plain_text
: "";
const tags =
row.properties.Tags?.multi_select.map((tag) => tag.name) || []; // Ensure tags is always an array
const id = row.id || ""; // Ensure the Notion ID is being used

// Sanitize the title for cover path
const sanitizedTitle = sanitizeFileName(title);
let coverPath = '';

// If a cover URL exists, download and upload the image to Supabase
// Fetch fresh cover URL
let coverUrl = '';
if (row.cover) {
try {
coverUrl = await getFreshCoverUrl(notion, row.id);
} catch (error) {
sendLog(
controller,
`Error fetching fresh cover URL for project ${title}: ${
(error as Error).message
}`
);
}
}

// Proceed with image processing if coverUrl is available
let coverPath = '';
if (coverUrl) {
try {
sendLog(controller, `Downloading image for project: ${title}`);
const imageBuffer = await downloadImage(coverUrl); // Download image
coverPath = await uploadImageToSupabase(imageBuffer, `projects/${sanitizedTitle}/cover.webp`); // Upload to Supabase
coverPath = await uploadImageToSupabase(
imageBuffer,
`projects/${sanitizedTitle}/cover.webp`
); // Upload to Supabase
sendLog(controller, `Uploaded cover image for project: ${title}`);
} catch (error) {
sendLog(controller, `Error processing cover image for project ${title}: ${(error as Error).message}`);
sendLog(
controller,
`Error processing cover image for project ${title}: ${
(error as Error).message
}`
);
}
}

Expand Down Expand Up @@ -194,6 +255,9 @@ export async function updateProjects(controller: ReadableStreamDefaultController
sendLog(controller, "Projects data uploaded to Prisma database.");
} catch (error) {
console.error("Error retrieving or processing projects:", error);
sendLog(controller, `Error retrieving or processing projects: ${(error as Error).message}`);
sendLog(
controller,
`Error retrieving or processing projects: ${(error as Error).message}`
);
}
}
}

0 comments on commit b823fb5

Please sign in to comment.