Files
Admin_dash/app/api/rss/feeds/route.ts
2026-02-09 17:56:49 -05:00

92 lines
2.9 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server';
import { getDb } from '@/lib/db';
import Parser from 'rss-parser';
export const dynamic = 'force-dynamic';
export async function GET() {
const db = await getDb();
const feeds = await db.all(`
SELECT f.*, (SELECT COUNT(*) FROM rss_items WHERE feed_id = f.id) as item_count
FROM rss_feeds f ORDER BY f.created_at ASC
`);
return NextResponse.json(feeds);
}
export async function POST(req: NextRequest) {
const { url, name } = await req.json();
if (!url || typeof url !== 'string') {
return NextResponse.json({ error: 'URL is required' }, { status: 400 });
}
// Validate URL format
try {
new URL(url);
} catch {
return NextResponse.json({ error: 'Invalid URL format' }, { status: 400 });
}
// Validate it's actually an RSS feed
const parser = new Parser({ timeout: 5000 });
let parsed;
try {
parsed = await parser.parseURL(url);
} catch {
return NextResponse.json({ error: 'Could not parse RSS feed at this URL' }, { status: 400 });
}
const feedName = name?.trim() || parsed.title || new URL(url).hostname;
const db = await getDb();
try {
const result = await db.run(
'INSERT INTO rss_feeds (name, url) VALUES (?, ?)',
feedName, url.trim()
);
const feedId = result.lastID;
// Immediately fetch and cache items
for (const item of parsed.items || []) {
if (!item.title || !item.link) continue;
await db.run(
`INSERT OR IGNORE INTO rss_items (feed_id, title, link, pub_date, creator, snippet)
VALUES (?, ?, ?, ?, ?, ?)`,
feedId,
item.title,
item.link,
item.pubDate || item.isoDate || null,
item.creator || item.author || null,
(item.contentSnippet || item.content || '').substring(0, 500) || null
);
}
await db.run(
'UPDATE rss_feeds SET last_fetched = ? WHERE id = ?',
new Date().toISOString(), feedId
);
const feed = await db.get('SELECT * FROM rss_feeds WHERE id = ?', feedId);
return NextResponse.json(feed, { status: 201 });
} catch (err: unknown) {
if (err instanceof Error && err.message.includes('UNIQUE')) {
return NextResponse.json({ error: 'Feed URL already exists' }, { status: 409 });
}
throw err;
}
}
export async function DELETE(req: NextRequest) {
const { id } = await req.json();
if (!id) {
return NextResponse.json({ error: 'Feed id is required' }, { status: 400 });
}
const db = await getDb();
await db.run('DELETE FROM rss_items WHERE feed_id = ?', id);
await db.run('DELETE FROM rss_feeds WHERE id = ?', id);
return NextResponse.json({ ok: true });
}