Initial commit

This commit is contained in:
twotalesanimation
2026-06-11 10:46:09 +02:00
commit 81ad7e4ea9
223 changed files with 39530 additions and 0 deletions
+109
View File
@@ -0,0 +1,109 @@
// app/api/videos/[id]/route.ts
import { NextResponse } from "next/server";
import { prisma } from "../../../../lib/prisma";
import { getServerSession } from "next-auth";
import { authOptions } from "../../../../lib/auth-options";
import { getVideoUrls } from "../../../../lib/video-urls";
export async function GET(req: Request, context: any) {
try {
// unwrap params
let params = context?.params;
if (typeof params?.then === "function") params = await params;
const id = params?.id;
if (!id) return NextResponse.json({ error: "Missing video id" }, { status: 400 });
const session = await getServerSession(authOptions);
if (!session?.user?.email) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
const user = await prisma.user.findUnique({
where: { email: session.user.email },
include: {
enrollments: true,
},
});
if (!user) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
const video = await prisma.video.findUnique({
where: { id },
include: {
playlist: {
include: {
course: true,
courses: true,
},
},
uploader: {
select: {
id: true,
name: true,
image: true,
},
},
videoCourses: true,
},
});
if (!video) return NextResponse.json({ error: "Not found" }, { status: 404 });
const userCourseIds = user.enrollments.map((enrollment) => enrollment.courseId);
const playlistCourseIds = new Set<string>([video.playlist.courseId]);
(video.playlist.courses || []).forEach((mapping) => {
playlistCourseIds.add(mapping.courseId);
});
const hasPlaylistAccess = [...playlistCourseIds].some((courseId) =>
userCourseIds.includes(courseId)
);
if (!hasPlaylistAccess) {
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
}
const restrictedCourseIds = (video.videoCourses || [])
.filter((assignment) => assignment.exclusive)
.map((assignment) => assignment.courseId);
if (
restrictedCourseIds.length > 0 &&
!restrictedCourseIds.some((courseId) => userCourseIds.includes(courseId))
) {
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
}
// Find the next video (index = current.index + 1)
const next = await prisma.video.findFirst({
where: {
playlistId: video.playlistId,
index: video.index + 1,
},
include: {
uploader: {
select: {
id: true,
name: true,
image: true,
},
},
},
});
// Add video URLs with HLS support
const videoUrls = getVideoUrls(video.id, video.url, video.transcodingStatus as any);
const responseVideo = {
...video,
videoUrls,
transcodingStatus: video.transcodingStatus,
restrictedCourseIds,
};
// Ensure we return the URL field explicitly (player expects `video.url`).
return NextResponse.json({ video: responseVideo, next });
} catch (err: any) {
console.error("GET /api/videos/[id] error:", err);
return NextResponse.json({ error: "Server error" }, { status: 500 });
}
}