import { APPWRITE_ALMEIRA_CONFIG } from '@/lib/appwrite'; import { createAdminClient } from '@/lib/appwrite.server'; import { Query } from 'node-appwrite'; import { GlobalSidebar, hasSidebarContent } from '@/components/AdWrappers'; import { Calendar, User, ArrowLeft, Newspaper, Tag } from 'lucide-react'; import Link from 'next/link'; import { decodeHtmlEntities } from '@/lib/utils'; import DOMPurify from 'isomorphic-dompurify'; import { Metadata, ResolvingMetadata } from 'next'; function formatTextToHtml(text: string) { if (!text) return ''; // Normalize any video preview URLs to view URLs for legacy content const normalizedText = text .replace(/(]*src=["'])([^"']*)\/preview\?([^"']*["'])/gi, '$1$2/view?$3') .replace(/(]*src=["'])([^"']*)\/preview\?([^"']*["'])/gi, '$1$2/view?$3'); // Si ya contiene etiquetas estructurales de HTML (párrafos, saltos, divs, listas), lo devolvemos tal cual if (/<\/?(?:p|br|div|h[1-6]|ul|ol|li|table)[^>]*>/i.test(normalizedText)) { return normalizedText; } // Convertimos texto plano con saltos de línea a párrafos y
, permitiendo que etiquetas inline como o `; } } else if (videoUrlField.includes('vimeo.com')) { const match = videoUrlField.match(/vimeo\.com\/(\d+)/); if (match) { const videoId = match[1]; videoHtml = ``; } } else { videoHtml = ``; } } // 2. Look for video tag inside content (first occurrence) if (!videoHtml && content) { const videoRegex = /]*>([\s\S]*?)<\/video>/i; const match = videoRegex.exec(content); if (match) { videoHtml = match[0]; cleanContent = content.replace(videoRegex, ''); } } // 3. Look for youtube iframe/div inside content (first occurrence) if (!videoHtml && content) { const ytRegex = /]*data-youtube-video[^>]*>([\s\S]*?)<\/div>/i; const ytMatch = ytRegex.exec(content); if (ytMatch) { videoHtml = ytMatch[0]; cleanContent = content.replace(ytRegex, ''); } else { const iframeRegex = /]*src=["'][^"']*(?:youtube\.com|youtu\.be|vimeo\.com)[^"']*["'][^>]*>([\s\S]*?)<\/iframe>/i; const iframeMatch = iframeRegex.exec(content); if (iframeMatch) { videoHtml = iframeMatch[0]; cleanContent = content.replace(iframeRegex, ''); } } } return { videoHtml, cleanContent }; } function styleHeroMedia(html: string, posterUrl?: string): string { if (!html) return ''; if (html.includes(']*>[\s\S]*?<\/iframe>/i); if (iframeMatch) { return styleHeroMedia(iframeMatch[0]); } } return html; } async function fetchPostData(slugOrId: string) { if (!slugOrId || typeof slugOrId !== 'string' || slugOrId.includes('.')) return null; try { const client = await createAdminClient(); const dbId = APPWRITE_ALMEIRA_CONFIG.databaseId; // 1. Try by slug let res = await client.databases.listDocuments(dbId, 'posts', [ Query.equal('slug', slugOrId), Query.limit(1) ]); if (res.documents.length > 0) return res.documents[0]; // 2. Try by $id (fallback) try { return await client.databases.getDocument(dbId, 'posts', slugOrId); } catch (e) { return null; } } catch (e) { if (!slugOrId.includes('favicon')) { console.error("Post detail fetch error for slug:", slugOrId, e); } return null; } } export async function generateMetadata( { params }: { params: Promise<{ slug: string }> }, parent: ResolvingMetadata ): Promise { const { slug } = await params; const post = await fetchPostData(slug); if (!post) { return { title: 'No encontrado - Almeira Web', description: 'La publicación solicitada no existe o ha sido eliminada.' }; } const title = decodeHtmlEntities(post.titulo); const description = post.resumen_redes ? decodeHtmlEntities(post.resumen_redes) : (post.contenido?.replace(/<[^>]*>?/gm, '').substring(0, 160) + '...'); const PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '6aef63d9002c07371b40'; const ENDPOINT = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://nyc.cloud.appwrite.io/v1'; let imagenUrl = post.og_image_url || null; if (post.imagen_destacada_id) { try { const client = await createAdminClient(); const mediaRes = await client.databases.getDocument(APPWRITE_ALMEIRA_CONFIG.databaseId, 'media', post.imagen_destacada_id); if (mediaRes) { imagenUrl = `${ENDPOINT}/storage/buckets/${mediaRes.bucket_id}/files/${mediaRes.file_id}/preview?project=${PROJECT_ID}&width=1200&height=630&quality=90`; } } catch(e) {} } const previousImages = (await parent).openGraph?.images || []; const images = imagenUrl ? [imagenUrl, ...previousImages] : previousImages; return { title: title, description: description, openGraph: { title: title, description: description, images: images, type: 'article', publishedTime: post.fecha_publicacion || post.$createdAt, }, twitter: { card: 'summary_large_image', title: title, description: description, images: images, } }; } export default async function NoticiaDetail({ params }: { params: Promise<{ slug: string }> }) { const { slug } = await params; const post = await fetchPostData(slug); const hasSidebar = await hasSidebarContent(); if (!post) { return (

404 - SEÑAL PERDIDA

No hemos podido localizar la transmisión solicitada en el núcleo central.

VOLVER AL FEED
); } const PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '6aef63d9002c07371b40'; const ENDPOINT = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://nyc.cloud.appwrite.io/v1'; let imagenUrl = post.og_image_url || null; const isSquare = post.tipo === 'evento' || post.tipo === 'aviso' || (typeof post.tipo_publicacion_id === 'object' && (post.tipo_publicacion_id.codigo === 'EVENTO' || post.tipo_publicacion_id.codigo === 'CLASIFICADO')); const imgHeight = isSquare ? 640 : 360; if (post.imagen_destacada_id) { try { const client = await createAdminClient(); const mediaRes = await client.databases.getDocument(APPWRITE_ALMEIRA_CONFIG.databaseId, 'media', post.imagen_destacada_id); if (mediaRes) { imagenUrl = `${ENDPOINT}/storage/buckets/${mediaRes.bucket_id}/files/${mediaRes.file_id}/preview?project=${PROJECT_ID}&width=640&height=${imgHeight}&quality=90`; } } catch(e) {} } const fechaObj = new Date(post.fecha_publicacion || post.$createdAt); const fechaFormateada = fechaObj.toLocaleDateString('es-ES', { day: '2-digit', month: 'long', year: 'numeric' }); // Extract video media if present const rawContent = post.contenido || ''; const { videoHtml, cleanContent } = extractMedia(rawContent, post.video_url); const styledHeroMedia = videoHtml ? styleHeroMedia(videoHtml, imagenUrl || undefined) : null; return (
Volver a la portada
{typeof post.tipo_publicacion_id === 'object' ? post.tipo_publicacion_id.descripcion : (post.tipo || 'Noticia')} {fechaFormateada}

{decodeHtmlEntities(post.titulo)}

{post.resumen_redes && (

{decodeHtmlEntities(post.resumen_redes)}

)}
{styledHeroMedia ? (
) : imagenUrl ? (
{post.titulo}
) : (
Almeira Web
)}
{hasSidebar && ( )}
); }