diff --git a/app/(browse)/_components/sidebar/following.tsx b/app/(browse)/_components/sidebar/following.tsx index 0826995..9daba4e 100644 --- a/app/(browse)/_components/sidebar/following.tsx +++ b/app/(browse)/_components/sidebar/following.tsx @@ -5,7 +5,13 @@ import { Follow, User } from "@prisma/client"; import { UserItem, UserItemSkeleton } from "./user-item"; interface FollowingProps { - data: (Follow & { following: User })[]; + data: (Follow & { + following: User & { + stream: { + isLive: boolean; + } | null; + }; + })[]; } export const Following = ({ data }: FollowingProps) => { @@ -28,7 +34,7 @@ export const Following = ({ data }: FollowingProps) => { key={follow.following.id} username={follow.following.username} imageUrl={follow.following.imageUrl} - isLive={true} + isLive={follow.following.stream?.isLive} /> ))} diff --git a/app/(browse)/_components/sidebar/recommended.tsx b/app/(browse)/_components/sidebar/recommended.tsx index 157facc..64abef0 100644 --- a/app/(browse)/_components/sidebar/recommended.tsx +++ b/app/(browse)/_components/sidebar/recommended.tsx @@ -5,7 +5,9 @@ import { User } from "@prisma/client"; import { UserItem, UserItemSkeleton } from "./user-item"; interface RecommendedProps { - data: User[]; + data: (User & { + stream: { isLive: boolean } | null; + })[]; } export const Recommended = ({ data }: RecommendedProps) => { @@ -26,7 +28,7 @@ export const Recommended = ({ data }: RecommendedProps) => { key={user.id} username={user.username} imageUrl={user.imageUrl} - isLive={true} + isLive={user.stream?.isLive} /> ))} diff --git a/app/api/webhooks/livekit/route.ts b/app/api/webhooks/livekit/route.ts new file mode 100644 index 0000000..f5d6d68 --- /dev/null +++ b/app/api/webhooks/livekit/route.ts @@ -0,0 +1,42 @@ +import { db } from "@/lib/db"; +import { WebhookReceiver } from "livekit-server-sdk"; +import { headers } from "next/headers"; + +const receiver = new WebhookReceiver( + process.env.LIVEKIT_API_KEY!, + process.env.LIVEKIT_API_SECRET! +); + +export async function POST(req: Request) { + const body = await req.text(); + const headerPayload = headers(); + const authorization = headerPayload.get("Authorization"); + + if (!authorization) { + return new Response("No authorization header", { status: 400 }); + } + + const event = receiver.receive(body, authorization); + + if (event.event === "ingress_started") { + await db.stream.update({ + where: { + ingressId: event.ingressInfo?.ingressId, + }, + data: { + isLive: true, + }, + }); + } + + if (event.event === "ingress_ended") { + await db.stream.update({ + where: { + ingressId: event.ingressInfo?.ingressId, + }, + data: { + isLive: false, + }, + }); + } +} diff --git a/lib/follow-service.ts b/lib/follow-service.ts index 34d0ce8..a7f8f44 100644 --- a/lib/follow-service.ts +++ b/lib/follow-service.ts @@ -17,8 +17,28 @@ export const getFollowedUsers = async () => { }, }, include: { - following: true, + following: { + include: { + stream: { + select: { + isLive: true, + }, + }, + }, + }, }, + orderBy: [ + { + following: { + stream: { + isLive: "desc", + }, + }, + }, + { + createdAt: "desc", + }, + ], }); return followedUsers; diff --git a/lib/recommended-service.ts b/lib/recommended-service.ts index 4278155..a510a37 100644 --- a/lib/recommended-service.ts +++ b/lib/recommended-service.ts @@ -42,15 +42,43 @@ export const getRecommended = async () => { }, ], }, - orderBy: { - createAt: "desc", + include: { + stream: { + select: { + isLive: true, + }, + }, }, + orderBy: [ + { + stream: { + isLive: "desc", + }, + }, + { + createAt: "desc", + }, + ], }); } else { users = await db.user.findMany({ - orderBy: { - createAt: "desc", + include: { + stream: { + select: { + isLive: true, + }, + }, }, + orderBy: [ + { + stream: { + isLive: "desc", + }, + }, + { + createAt: "desc", + }, + ], }); }