120 lines
3.6 KiB
TypeScript
120 lines
3.6 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { prisma } from "@/lib/prisma";
|
|
|
|
// GET /api/aweme/around?awemeId=xxxx
|
|
// Response: { prev?: { type: 'video'|'image', aweme_id: string, created_at: string }, next?: { ... } }
|
|
export async function GET(req: NextRequest) {
|
|
const { searchParams } = new URL(req.url);
|
|
const awemeId = searchParams.get("awemeId");
|
|
if (!awemeId) {
|
|
return NextResponse.json({ error: "missing awemeId" }, { status: 400 });
|
|
}
|
|
|
|
// Find current item timestamp from either table
|
|
const [video, post] = await Promise.all([
|
|
prisma.video.findUnique({
|
|
where: { aweme_id: awemeId },
|
|
select: { aweme_id: true, created_at: true },
|
|
}),
|
|
prisma.imagePost.findUnique({
|
|
where: { aweme_id: awemeId },
|
|
select: { aweme_id: true, created_at: true },
|
|
}),
|
|
]);
|
|
|
|
const current = video ?? post;
|
|
if (!current) {
|
|
return NextResponse.json({ error: "aweme not found" }, { status: 404 });
|
|
}
|
|
|
|
const createdAt = current.created_at as unknown as Date;
|
|
|
|
// Newer than current (prev in a desc-ordered feed): pick the nearest newer by created_at
|
|
const [newerVideo, newerPost] = await Promise.all([
|
|
prisma.video.findFirst({
|
|
where: { created_at: { gt: createdAt } },
|
|
orderBy: { created_at: "asc" },
|
|
select: { aweme_id: true, created_at: true },
|
|
}),
|
|
prisma.imagePost.findFirst({
|
|
where: { created_at: { gt: createdAt } },
|
|
orderBy: { created_at: "asc" },
|
|
select: { aweme_id: true, created_at: true },
|
|
}),
|
|
]);
|
|
|
|
// Older than current (next in a desc-ordered feed): pick the nearest older by created_at
|
|
const [olderVideo, olderPost] = await Promise.all([
|
|
prisma.video.findFirst({
|
|
where: { created_at: { lt: createdAt } },
|
|
orderBy: { created_at: "desc" },
|
|
select: { aweme_id: true, created_at: true },
|
|
}),
|
|
prisma.imagePost.findFirst({
|
|
where: { created_at: { lt: createdAt } },
|
|
orderBy: { created_at: "desc" },
|
|
select: { aweme_id: true, created_at: true },
|
|
}),
|
|
]);
|
|
|
|
const pickPrev = (() => {
|
|
const cands: {
|
|
type: "video" | "image";
|
|
aweme_id: string;
|
|
created_at: Date;
|
|
}[] = [];
|
|
if (newerVideo)
|
|
cands.push({
|
|
type: "video",
|
|
aweme_id: newerVideo.aweme_id,
|
|
created_at: newerVideo.created_at as unknown as Date,
|
|
});
|
|
if (newerPost)
|
|
cands.push({
|
|
type: "image",
|
|
aweme_id: newerPost.aweme_id,
|
|
created_at: newerPost.created_at as unknown as Date,
|
|
});
|
|
if (cands.length === 0) return undefined;
|
|
// nearest newer -> minimal created_at
|
|
cands.sort((a, b) => +a.created_at - +b.created_at);
|
|
const h = cands[0];
|
|
return {
|
|
type: h.type,
|
|
aweme_id: h.aweme_id,
|
|
created_at: h.created_at.toISOString(),
|
|
};
|
|
})();
|
|
|
|
const pickNext = (() => {
|
|
const cands: {
|
|
type: "video" | "image";
|
|
aweme_id: string;
|
|
created_at: Date;
|
|
}[] = [];
|
|
if (olderVideo)
|
|
cands.push({
|
|
type: "video",
|
|
aweme_id: olderVideo.aweme_id,
|
|
created_at: olderVideo.created_at as unknown as Date,
|
|
});
|
|
if (olderPost)
|
|
cands.push({
|
|
type: "image",
|
|
aweme_id: olderPost.aweme_id,
|
|
created_at: olderPost.created_at as unknown as Date,
|
|
});
|
|
if (cands.length === 0) return undefined;
|
|
// nearest older -> maximal created_at among older
|
|
cands.sort((a, b) => +b.created_at - +a.created_at);
|
|
const h = cands[0];
|
|
return {
|
|
type: h.type,
|
|
aweme_id: h.aweme_id,
|
|
created_at: h.created_at.toISOString(),
|
|
};
|
|
})();
|
|
|
|
return NextResponse.json({ prev: pickPrev ?? null, next: pickNext ?? null });
|
|
}
|