From 76d05445f7917e5e7ebdbff8b3638fe1dbe91b87 Mon Sep 17 00:00:00 2001 From: Sargam Poudel Date: Thu, 21 Nov 2024 12:52:39 +0530 Subject: [PATCH] feat: add rest logic for video playback --- .../migration.sql | 5 +++ src/actions/user/index.ts | 18 ++++----- src/components/AppxVideoPlayer.tsx | 38 +++++++++++-------- src/components/VideoPlayer2.tsx | 12 ++---- src/components/VideoPlayerSegment.tsx | 3 ++ src/components/admin/ContentRenderer.tsx | 3 ++ .../admin/ContentRendererClient.tsx | 1 + 7 files changed, 47 insertions(+), 33 deletions(-) create mode 100644 prisma/migrations/20241121062529_add_appx_fields/migration.sql diff --git a/prisma/migrations/20241121062529_add_appx_fields/migration.sql b/prisma/migrations/20241121062529_add_appx_fields/migration.sql new file mode 100644 index 000000000..396bd9092 --- /dev/null +++ b/prisma/migrations/20241121062529_add_appx_fields/migration.sql @@ -0,0 +1,5 @@ +-- AlterTable +ALTER TABLE "User" ADD COLUMN "appxAuthToken" TEXT; + +-- AlterTable +ALTER TABLE "VideoMetadata" ADD COLUMN "appxVideoId" TEXT; diff --git a/src/actions/user/index.ts b/src/actions/user/index.ts index 09802bdab..7f6f960a7 100644 --- a/src/actions/user/index.ts +++ b/src/actions/user/index.ts @@ -37,7 +37,7 @@ type GetAppxAuthTokenResponse = { } export const GetAppxAuthToken = async (): Promise => { - const session = await getServerSession(authOptions) + const session = await getServerSession(authOptions); if (!session || !session.user) throw new Error("User is not logged in"); const user = await db.user.findFirst({ @@ -52,21 +52,22 @@ export const GetAppxAuthToken = async (): Promise => { } }); - if (!user) throw new Error("User not found"); - return user -} + if (!user || !user.appxAuthToken) throw new Error("User not found"); + return user; +}; export const GetAppxVideoPlayerUrl = async (courseId: string, videoId: string): Promise => { const { name, email, appxAuthToken, appxUserId } = await GetAppxAuthToken(); const url = `${process.env.APPX_BASE_API}/get/fetchVideoDetailsById?course_id=${courseId}&video_id=${videoId}&ytflag=${1}&folder_wise_course=${1}`; + const config = { url, - method: "get", + method: 'get', maxBodyLength: Infinity, headers: { Authorization: appxAuthToken, - "Auth-Key": process.env.APPX_AUTH_KEY, - "User-Id": appxUserId, + 'Auth-Key': process.env.APPX_AUTH_KEY, + 'User-Id': appxUserId, }, }; @@ -74,5 +75,4 @@ export const GetAppxVideoPlayerUrl = async (courseId: string, videoId: string): const { video_player_token, video_player_url } = res.data.data; const full_video_url = `${video_player_url}${video_player_token}&watermark=${name}%0A${email}`; return full_video_url; -} - +}; diff --git a/src/components/AppxVideoPlayer.tsx b/src/components/AppxVideoPlayer.tsx index 917265369..8e3fcf662 100644 --- a/src/components/AppxVideoPlayer.tsx +++ b/src/components/AppxVideoPlayer.tsx @@ -1,6 +1,9 @@ -"use client"; -import { GetAppxVideoPlayerUrl } from "@/actions/user"; -import { useEffect, useState } from "react"; +'use client'; +import { GetAppxVideoPlayerUrl } from '@/actions/user'; +import { signOut } from 'next-auth/react'; +import { useEffect, useRef, useState } from 'react'; +import { Button } from 'react-day-picker'; +import { toast } from 'sonner'; export const AppxVideoPlayer = ({ courseId, @@ -9,28 +12,31 @@ export const AppxVideoPlayer = ({ courseId: string; videoId: string; }) => { - const [url, setUrl] = useState(""); + const [url, setUrl] = useState(''); + const doneRef = useRef(false); useEffect(() => { (async () => { + if (doneRef.current) return; + doneRef.current = true; try { - const videoUrl = await GetAppxVideoPlayerUrl(courseId, videoId) - setUrl(videoUrl) + const videoUrl = await GetAppxVideoPlayerUrl(courseId, videoId); + setUrl(videoUrl); } catch { - if (window === undefined) return; - location.href = '/api/auth/signin'; + toast.info('This is a new type of video player', { + description: 'Please relogin to continue', + action: { + label: 'Relogin', + onClick: () => signOut(), + }, + }); } })(); - }, []) + }, []); if (!url.length) { return

Loading...

; } - return ( - - ); -} + return ; +}; diff --git a/src/components/VideoPlayer2.tsx b/src/components/VideoPlayer2.tsx index 7e7151e7f..3916917da 100644 --- a/src/components/VideoPlayer2.tsx +++ b/src/components/VideoPlayer2.tsx @@ -25,6 +25,7 @@ interface VideoPlayerProps { onReady?: (player: Player) => void; subtitles?: string; contentId: number; + appxVideoId?: string; onVideoEnd: () => void; } @@ -38,6 +39,7 @@ export const VideoPlayer: FunctionComponent = ({ onReady, subtitles, onVideoEnd, + appxVideoId, }) => { const videoRef = useRef(null); const playerRef = useRef(null); @@ -472,17 +474,11 @@ export const VideoPlayer: FunctionComponent = ({ return regex.test(url); }; - const isAppxEncryptedVideo = (url: string) => { - return url.startsWith('https://player.akamai.net.in/secure-player'); - }; - if (isYoutubeUrl(vidUrl)) return ; //TODO: Figure out how to get the courseId - if (isAppxEncryptedVideo(vidUrl)) - return ( - - ); + if (appxVideoId) + return ; return (
void; } @@ -34,6 +35,7 @@ export const VideoPlayerSegment: FunctionComponent = ({ segments, videoJsOptions, onVideoEnd, + appxVideoId, }) => { const playerRef = useRef(null); @@ -101,6 +103,7 @@ export const VideoPlayerSegment: FunctionComponent = ({ contentId={contentId} subtitles={subtitles} options={videoJsOptions} + appxVideoId={appxVideoId} onVideoEnd={onVideoEnd} onReady={handlePlayerReady} /> diff --git a/src/components/admin/ContentRenderer.tsx b/src/components/admin/ContentRenderer.tsx index e29bc143a..c6b5c35fc 100644 --- a/src/components/admin/ContentRenderer.tsx +++ b/src/components/admin/ContentRenderer.tsx @@ -37,6 +37,7 @@ export const getMetadata = async (contentId: number) => { contentId, }, }); + if (!metadata) { return null; } @@ -85,6 +86,7 @@ export const getMetadata = async (contentId: number) => { slides: metadata['slides'], segments: metadata['segments'], thumbnails: metadata['thumbnail_mosiac_url'], + appxVideoId: metadata['appxVideoId'], }; if (user?.bunnyProxyEnabled) { @@ -102,6 +104,7 @@ export const getMetadata = async (contentId: number) => { slides: metadata['slides'], segments: metadata['segments'], thumbnails: metadata['thumbnail_mosiac_url'], + appxVideoId: metadata['appxVideoId'], }; const isHighestQualityUrlAccessible = await isUrlAccessible(mainUrls['1080']); diff --git a/src/components/admin/ContentRendererClient.tsx b/src/components/admin/ContentRendererClient.tsx index 018aecc71..4f8881421 100644 --- a/src/components/admin/ContentRendererClient.tsx +++ b/src/components/admin/ContentRendererClient.tsx @@ -79,6 +79,7 @@ export const ContentRendererClient = ({ contentId={content.id} subtitles={metadata.subtitles} thumbnails={[]} + appxVideoId={metadata.appxVideoId} segments={metadata?.segments || []} videoJsOptions={{ playbackrates: [0.5, 1, 1.25, 1.5, 1.75, 2],