feat(brandbook): anadir ingesta automatica de fuentes desde URL web en seccion Fuentes
This commit is contained in:
@@ -55,15 +55,17 @@ export async function POST(req: NextRequest) {
|
||||
|
||||
let filename = 'pegado.txt';
|
||||
let text = '';
|
||||
let url = '';
|
||||
const ctype = req.headers.get('content-type') || '';
|
||||
if (ctype.includes('multipart/form-data')) {
|
||||
const form = await req.formData();
|
||||
const file = form.get('file');
|
||||
const pasted = form.get('text');
|
||||
if (typeof pasted === 'string' && pasted.trim()) {
|
||||
url = String(form.get('url') || '').trim();
|
||||
if (!url && typeof pasted === 'string' && pasted.trim()) {
|
||||
text = pasted;
|
||||
filename = String(form.get('filename') || 'pegado.txt');
|
||||
} else if (file && typeof file === 'object' && 'arrayBuffer' in file) {
|
||||
} else if (!url && file && typeof file === 'object' && 'arrayBuffer' in file) {
|
||||
const f = file as File;
|
||||
filename = f.name || 'upload.txt';
|
||||
const lower = filename.toLowerCase();
|
||||
@@ -87,11 +89,80 @@ export async function POST(req: NextRequest) {
|
||||
const body = (await req.json().catch(() => ({}))) as {
|
||||
text?: string;
|
||||
filename?: string;
|
||||
url?: string;
|
||||
};
|
||||
url = String(body.url || '').trim();
|
||||
text = String(body.text || '');
|
||||
filename = String(body.filename || 'pegado.txt');
|
||||
}
|
||||
|
||||
if (url) {
|
||||
if (!url.startsWith('http://') && !url.startsWith('https://')) {
|
||||
return NextResponse.json(
|
||||
{ error: 'La URL debe empezar por http:// o https://' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
try {
|
||||
const resp = await fetch(url, {
|
||||
headers: {
|
||||
'User-Agent':
|
||||
'Mozilla/5.0 (compatible; 4VenturesBrandbot/1.0; +https://4ventures.es)',
|
||||
Accept: 'text/html,application/xhtml+xml,text/plain;q=0.9,*/*;q=0.8',
|
||||
},
|
||||
signal: AbortSignal.timeout(15000),
|
||||
});
|
||||
if (!resp.ok) {
|
||||
return NextResponse.json(
|
||||
{ error: `Error al acceder a la URL: HTTP ${resp.status}` },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
const raw = await resp.text();
|
||||
const clean = raw
|
||||
.replace(/<script[\s\S]*?<\/script>/gi, '')
|
||||
.replace(/<style[\s\S]*?<\/style>/gi, '')
|
||||
.replace(/<noscript[\s\S]*?<\/noscript>/gi, '')
|
||||
.replace(/<svg[\s\S]*?<\/svg>/gi, '')
|
||||
.replace(/<\/(p|div|h[1-6]|li|tr)>/gi, '\n\n')
|
||||
.replace(/<br\s*[\/]?>/gi, '\n');
|
||||
|
||||
text = clean
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, "'")
|
||||
.replace(/ /g, ' ')
|
||||
.replace(/<[^>]+>/g, ' ')
|
||||
.replace(/[ \t]+/g, ' ')
|
||||
.replace(/\n\s*\n\s*\n+/g, '\n\n')
|
||||
.trim();
|
||||
|
||||
try {
|
||||
const parsed = new URL(url);
|
||||
const pathSegments = parsed.pathname.split('/').filter(Boolean);
|
||||
const lastSeg = pathSegments[pathSegments.length - 1];
|
||||
filename = lastSeg
|
||||
? lastSeg.endsWith('.html')
|
||||
? lastSeg
|
||||
: `${lastSeg}.txt`
|
||||
: `${parsed.hostname}.txt`;
|
||||
} catch {
|
||||
filename = 'fuente-url.txt';
|
||||
}
|
||||
} catch (err) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: `No se pudo conectar a la URL: ${
|
||||
err instanceof Error ? err.message : String(err)
|
||||
}`,
|
||||
},
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!text.trim()) {
|
||||
return NextResponse.json({ error: 'Sin texto' }, { status: 400 });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user