Normalize pub_date to ISO 8601 on insert so SQLite datetime comparisons work correctly. Migrate existing RFC 2822 dates. Change 1h filter to 12h. Add react-grid-layout with persistent drag/resize and reset button. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
91 lines
2.6 KiB
TypeScript
91 lines
2.6 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server';
|
|
import { getDb } from '@/lib/db';
|
|
|
|
export const dynamic = 'force-dynamic';
|
|
|
|
export async function GET(req: NextRequest) {
|
|
const { searchParams } = new URL(req.url);
|
|
const q = searchParams.get('q');
|
|
const feedId = searchParams.get('feed_id');
|
|
const bookmarked = searchParams.get('bookmarked');
|
|
const since = searchParams.get('since');
|
|
const limit = parseInt(searchParams.get('limit') || '50', 10);
|
|
const offset = parseInt(searchParams.get('offset') || '0', 10);
|
|
|
|
const db = await getDb();
|
|
|
|
const conditions: string[] = [];
|
|
const params: (string | number)[] = [];
|
|
|
|
if (q) {
|
|
conditions.push('(i.title LIKE ? OR i.snippet LIKE ?)');
|
|
params.push(`%${q}%`, `%${q}%`);
|
|
}
|
|
if (feedId) {
|
|
conditions.push('i.feed_id = ?');
|
|
params.push(parseInt(feedId, 10));
|
|
}
|
|
if (bookmarked === '1') {
|
|
conditions.push('i.bookmarked = 1');
|
|
}
|
|
if (since) {
|
|
const sinceMap: Record<string, string> = {
|
|
'12h': '-12 hours',
|
|
'24h': '-24 hours',
|
|
'7d': '-7 days',
|
|
'30d': '-30 days',
|
|
};
|
|
const modifier = sinceMap[since];
|
|
if (modifier) {
|
|
conditions.push("i.pub_date >= datetime('now', ?)");
|
|
params.push(modifier);
|
|
}
|
|
}
|
|
|
|
const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
|
|
|
|
const items = await db.all(
|
|
`SELECT i.*, f.name as feed_name, f.url as feed_url
|
|
FROM rss_items i
|
|
LEFT JOIN rss_feeds f ON f.id = i.feed_id
|
|
${where}
|
|
ORDER BY i.pub_date DESC
|
|
LIMIT ? OFFSET ?`,
|
|
...params, limit, offset
|
|
);
|
|
|
|
return NextResponse.json(items);
|
|
}
|
|
|
|
export async function PATCH(req: NextRequest) {
|
|
const body = await req.json();
|
|
const { id, read, bookmarked } = body;
|
|
|
|
if (!id) {
|
|
return NextResponse.json({ error: 'Item id is required' }, { status: 400 });
|
|
}
|
|
|
|
const db = await getDb();
|
|
const updates: string[] = [];
|
|
const params: (number)[] = [];
|
|
|
|
if (read !== undefined) {
|
|
updates.push('read = ?');
|
|
params.push(read ? 1 : 0);
|
|
}
|
|
if (bookmarked !== undefined) {
|
|
updates.push('bookmarked = ?');
|
|
params.push(bookmarked ? 1 : 0);
|
|
}
|
|
|
|
if (updates.length === 0) {
|
|
return NextResponse.json({ error: 'Nothing to update' }, { status: 400 });
|
|
}
|
|
|
|
params.push(id);
|
|
await db.run(`UPDATE rss_items SET ${updates.join(', ')} WHERE id = ?`, ...params);
|
|
|
|
const item = await db.get('SELECT * FROM rss_items WHERE id = ?', id);
|
|
return NextResponse.json(item);
|
|
}
|