Files
Mebbling/app/api/export/sources/[id]/route.ts
T

16 lines
1.7 KiB
TypeScript

import { NextResponse } from "next/server";
import { requireUser } from "@/lib/auth";
import { db } from "@/lib/db";
function postMarkdown(post: any) { return `## ${post.remote_created_at || post.created_at}\n\n${post.content}\n`; }
export async function GET(request: Request, { params }: { params: Promise<{ id: string }> }) {
const user = await requireUser(); const { id: rawId } = await params; const id = Number(rawId); const source = db.prepare("SELECT id,name,base_url,integration_type,rss_feed_url,created_at FROM sources WHERE id=?").get(id) as any;
if (!source) return NextResponse.json({ error: "Not found" }, { status: 404 });
if (!db.prepare("SELECT 1 FROM source_members WHERE source_id=? AND user_id=?").get(id, user.id)) return NextResponse.json({ error: "Forbidden" }, { status: 403 });
const posts = db.prepare("SELECT id,content,visibility,tags_json,attachments_json,origin,remote_created_at,remote_updated_at,remote_url,created_at,updated_at FROM posts WHERE source_id=? ORDER BY COALESCE(remote_created_at,created_at)").all(id) as any[];
const format = new URL(request.url).searchParams.get("format") === "markdown" ? "markdown" : "json";
const body = format === "markdown" ? `# ${source.name}\n\n${posts.map(postMarkdown).join("\n---\n\n")}` : JSON.stringify({ version: 1, exportedAt: new Date().toISOString(), source, posts: posts.map((post) => ({ ...post, tags: JSON.parse(post.tags_json || "[]"), attachments: JSON.parse(post.attachments_json || "[]") })) }, null, 2);
return new NextResponse(body, { headers: { "Content-Type": format === "markdown" ? "text/markdown; charset=utf-8" : "application/json; charset=utf-8", "Content-Disposition": `attachment; filename="mebbling-source-${id}.${format === "markdown" ? "md" : "json"}"` } });
}