Files
vfxreview/app/api/ext/shots/lookup/route.ts
T
twotalesanimation 75d5149bea
Deploy / deploy (push) Successful in 3m12s
versioning added
2026-06-25 22:19:22 +02:00

108 lines
3.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
// ── Auth ─────────────────────────────────────────────────────────────────────
function isAuthorized(req: NextRequest): boolean {
const apiKey = process.env.API_SECRET_KEY;
if (!apiKey) return false;
const authHeader = req.headers.get("authorization") ?? "";
if (authHeader.startsWith("Bearer ")) return authHeader.slice(7) === apiKey;
return (req.headers.get("x-api-key") ?? "") === apiKey;
}
// ── GET /api/ext/shots/lookup ─────────────────────────────────────────────────
//
// Look up a single shot by its shot code and (optionally) project code.
// Designed for use in Nuke/After Effects/Blender pipeline tools.
//
// Query params:
// shotCode (required) e.g. UNG_108_004_010
// projectCode (recommended) e.g. UNG_108 disambiguates if same code appears across projects
//
// Example:
// GET /api/ext/shots/lookup?shotCode=UNG_108_004_010&projectCode=UNG_108
// Authorization: Bearer <API_SECRET_KEY>
export async function GET(req: NextRequest) {
if (!isAuthorized(req)) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
const { searchParams } = new URL(req.url);
const shotCode = searchParams.get("shotCode")?.trim();
const projectCode = searchParams.get("projectCode")?.trim();
if (!shotCode) {
return NextResponse.json({ error: "shotCode query param is required" }, { status: 400 });
}
const shot = await db.shot.findFirst({
where: {
shotCode,
...(projectCode ? { project: { code: projectCode } } : {}),
},
select: {
id: true,
shotCode: true,
scene: true,
episode: true,
sequence: true,
shotNumber: true,
description: true,
notes: true,
status: true,
priority: true,
frameStart: true,
frameEnd: true,
fps: true,
dueDate: true,
// EDL / pull CSV fields
sourceClip: true,
timecodeStart: true,
timecodeEnd: true,
clipDuration: true,
exrOutput: true,
seqTimecodeStart: true,
seqTimecodeEnd: true,
shotVersion: true,
thumbnailUrl: true,
createdAt: true,
updatedAt: true,
project: {
select: { id: true, name: true, code: true, showId: true },
},
artist: {
select: { id: true, name: true, email: true },
},
tasks: {
orderBy: { sortOrder: "asc" },
select: {
id: true,
title: true,
type: true,
status: true,
},
},
versions: {
where: { isLatest: true },
take: 1,
select: {
id: true,
versionNumber: true,
approvalStatus: true,
reviewStatus: true,
fileUrl: true,
createdAt: true,
},
},
},
});
if (!shot) {
return NextResponse.json({ error: "Shot not found" }, { status: 404 });
}
return NextResponse.json({ shot });
}