NeahFront9/app/api/news/route.ts
2025-04-15 11:54:30 +02:00

132 lines
3.8 KiB
TypeScript

import { NextResponse } from 'next/server';
import { Pool } from 'pg';
// PostgreSQL connection configuration
const pool = new Pool({
host: '172.16.0.104',
port: 5432,
database: 'rivacube',
user: 'alma',
password: 'rivacube',
connectionTimeoutMillis: 5000,
query_timeout: 5000
});
// Helper function to clean HTML content
function cleanHtmlContent(content: string): string {
if (!content) return '';
return content
.replace(/<[^>]*>/g, '')
.replace(/&nbsp;/g, ' ')
.replace(/&amp;/g, '&')
.replace(/&quot;/g, '"')
.replace(/&#39;/g, "'")
.trim();
}
// Helper function to format time
function formatDateTime(dateStr: string): { displayDate: string, timestamp: string } {
try {
const date = new Date(dateStr);
const day = date.getDate();
const month = date.toLocaleString('fr-FR', { month: 'short' }).toLowerCase();
return {
displayDate: `${day} ${month}.`, // Added dot for better styling
timestamp: date.toLocaleString('fr-FR', {
day: '2-digit',
month: 'short',
hour: '2-digit',
minute: '2-digit',
hour12: false
}).replace(',', ' à') // Format: "14 avr. à 15:30"
};
} catch (error) {
return { displayDate: 'N/A', timestamp: 'N/A' };
}
}
// Helper function to truncate text
function truncateText(text: string, maxLength: number): string {
if (!text || text.length <= maxLength) return text;
// Find the last space before maxLength to avoid cutting words
const lastSpace = text.lastIndexOf(' ', maxLength);
const truncated = text.substring(0, lastSpace > 0 ? lastSpace : maxLength).trim();
return truncated.replace(/[.,!?]$/, '') + '...';
}
// Helper function to format category
function formatCategory(category: string): string {
if (!category) return 'GENERAL';
// Make category names shorter and more readable
const categoryMap: { [key: string]: string } = {
'GLOBAL ISSUES - WORLD AFFAIRS': 'WORLD',
'UN NEWS - GLOBAL NEWS': 'UN NEWS',
'GLOBAL NEWS': 'WORLD',
};
const normalizedCategory = category.toUpperCase();
return categoryMap[normalizedCategory] || normalizedCategory;
}
// Helper function to format source
function formatSource(source: string): string {
if (!source) return '';
// Extract domain name without TLD and clean it up
const sourceName = source
.replace(/^(https?:\/\/)?(www\.)?/i, '')
.split('.')[0]
.toLowerCase()
.replace(/[^a-z0-9]/g, ' ')
.trim();
return sourceName.charAt(0).toUpperCase() + sourceName.slice(1);
}
export async function GET() {
let client;
try {
client = await pool.connect();
console.log('Connected to PostgreSQL database');
const result = await client.query(
'SELECT * FROM news ORDER BY date DESC LIMIT 3'
);
const formattedNews = result.rows.map(article => {
const { displayDate, timestamp } = formatDateTime(article.date);
return {
id: article.id,
title: truncateText(article.title, 55),
description: truncateText(article.description, 85),
displayDate,
timestamp,
source: formatSource(article.source),
category: formatCategory(article.category),
url: article.url || '#',
};
});
console.log(`Successfully fetched ${formattedNews.length} news articles`);
return NextResponse.json(formattedNews);
} catch (error) {
console.error('Error in news API:', {
error: error instanceof Error ? error.message : 'Unknown error',
stack: error instanceof Error ? error.stack : undefined,
timestamp: new Date().toISOString(),
});
return NextResponse.json(
{
error: 'Failed to fetch news',
details: error instanceof Error ? error.message : 'Unknown error',
timestamp: new Date().toISOString(),
},
{ status: 500 }
);
} finally {
if (client) {
client.release();
}
}
}