diff --git a/src/app/api/add/route.ts b/src/app/api/add/route.ts new file mode 100644 index 0000000..9536a12 --- /dev/null +++ b/src/app/api/add/route.ts @@ -0,0 +1,82 @@ +import { NextRequest, NextResponse } from "next/server"; +import { db, schema } from "@/lib/db"; +import { extractArticle } from "@/lib/utils/extract"; +import { v4 as uuidv4 } from "uuid"; +import { eq } from "drizzle-orm"; + +// GET /api/add?url=... - Simple endpoint for Apple Shortcuts (no auth required) +export async function GET(request: NextRequest) { + const url = request.nextUrl.searchParams.get("url"); + + if (!url) { + return NextResponse.json({ error: "URL is required" }, { status: 400 }); + } + + try { + const decodedUrl = decodeURIComponent(url); + + // Check if already exists + const existing = await db + .select() + .from(schema.articles) + .where(eq(schema.articles.url, decodedUrl)) + .limit(1); + + if (existing.length > 0) { + return NextResponse.json({ + success: true, + message: "Article already saved", + article: { id: existing[0].id, title: existing[0].title }, + }); + } + + // Extract and save + const extracted = await extractArticle(decodedUrl); + const id = uuidv4(); + + await db.insert(schema.articles).values({ + id, + url: decodedUrl, + title: extracted.title, + author: extracted.author, + siteName: extracted.siteName, + excerpt: extracted.excerpt, + content: extracted.content, + textContent: extracted.textContent, + leadImage: extracted.leadImage, + wordCount: extracted.wordCount, + }); + + return NextResponse.json({ + success: true, + message: "Article saved", + article: { id, title: extracted.title }, + }); + } catch (error) { + console.error("Error adding article:", error); + return NextResponse.json( + { error: error instanceof Error ? error.message : "Failed to save" }, + { status: 500 } + ); + } +} + +// POST /api/add - Alternative with JSON body +export async function POST(request: NextRequest) { + try { + const body = await request.json(); + const url = body.url; + + if (!url) { + return NextResponse.json({ error: "URL is required" }, { status: 400 }); + } + + // Reuse GET logic + const fakeRequest = new NextRequest( + new URL(`/api/add?url=${encodeURIComponent(url)}`, request.url) + ); + return GET(fakeRequest); + } catch { + return NextResponse.json({ error: "Invalid JSON body" }, { status: 400 }); + } +}