dvijaykrishnan's picture
feat: Implement new admin dashboard with video analysis, object moderation, and user management capabilities.
304bdf5
Raw
History Blame Contribute Delete
6.28 kB
"use server";
import { auth } from "@/lib/auth";
import { headers } from "next/headers";
import { ShowcaseService } from "../services/showcase.service";
import { SocialIngestService } from "../../discovery/services/social-ingest.service";
export async function quickAddVideoAction(formData: FormData) {
const session = await auth.api.getSession({
headers: await headers()
});
// For public showcase, we allow anonymous ingestion
const userId = session?.user?.id || null;
const url = formData.get("url") as string;
if (!url) return { success: false, error: "URL is required" };
const platform = SocialIngestService.detectPlatform(url);
if (!platform) {
return { success: false, error: "Unsupported platform. Supported: YouTube, TikTok, Instagram, Facebook" };
}
let videoId: string | null = null;
if (platform === 'youtube') {
const videoIdMatch = url.match(/(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/);
videoId = videoIdMatch ? videoIdMatch[1] : null;
} else if (platform === 'tiktok') {
const match = url.match(/\/video\/(\d+)/);
const rawId = match ? match[1] : `${Date.now()}`;
videoId = rawId.startsWith('tt-') ? rawId : `tt-${rawId}`;
} else if (platform === 'instagram') {
const match = url.match(/\/(?:p|reels|reel)\/([A-Za-z0-9_-]+)/);
const rawId = match ? match[1] : `${Date.now()}`;
videoId = rawId.startsWith('ig-') ? rawId : `ig-${rawId}`;
} else if (platform === 'facebook') {
const match = url.match(/[?&]v=([^&]+)/) || url.match(/\/share\/v\/([^/?]+)/) || url.match(/\/reel\/([^/?]+)/);
const rawId = match ? match[1] : `${Date.now()}`;
videoId = rawId.startsWith('fb-') ? rawId : `fb-${rawId}`;
} else {
videoId = `${platform}-${Date.now()}`;
}
if (!videoId) {
return { success: false, error: `Could not parse video ID from ${platform} URL` };
}
console.log(`[quickAddVideoAction] Ingesting: ${platform} | ID: ${videoId}`);
try {
const result = await ShowcaseService.ingestAndAnalyze(videoId, userId, {
skipAnalysis: true,
platform: platform,
url: url,
isInWorkbench: false // Preview mode: Don't add to dashboard yet
});
if (result.success) {
return { success: true, videoId };
}
return {
success: false,
error: result.error || "Failed to process video. The link might be private or restricted."
};
} catch (err) {
console.error(`[quickAddVideoAction] Exception:`, err);
return {
success: false,
error: "An unexpected error occurred. Please try again with a different link."
};
}
}
export async function checkCommunityVaultsAction(url: string) {
if (!url) return { success: false, error: "URL is required" };
const platform = SocialIngestService.detectPlatform(url);
if (!platform) return { success: false, error: "Unsupported platform" };
let videoId: string | null = null;
if (platform === 'youtube') {
const videoIdMatch = url.match(/(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/);
videoId = videoIdMatch ? videoIdMatch[1] : null;
} else if (platform === 'tiktok') {
const match = url.match(/\/video\/(\d+)/);
const rawId = match ? match[1] : null;
if (rawId) videoId = rawId.startsWith('tt-') ? rawId : `tt-${rawId}`;
} else if (platform === 'instagram') {
const match = url.match(/\/(?:p|reels|reel)\/([A-Za-z0-9_-]+)/);
const rawId = match ? match[1] : null;
if (rawId) videoId = rawId.startsWith('ig-') ? rawId : `ig-${rawId}`;
} else if (platform === 'facebook') {
const match = url.match(/[?&]v=([^&]+)/) || url.match(/\/share\/v\/([^/?]+)/) || url.match(/\/reel\/([^/?]+)/);
const rawId = match ? match[1] : null;
if (rawId) videoId = rawId.startsWith('fb-') ? rawId : `fb-${rawId}`;
}
if (!videoId) return { success: false, error: "Could not parse video ID" };
try {
const vaults = await ShowcaseService.getCommunityVaults(videoId);
return { success: true, vaults };
} catch (err) {
console.error(`[checkCommunityVaultsAction] Error:`, err);
return { success: false, error: "Failed to check community vaults" };
}
}
export async function requestAnalysisNotificationAction(videoId: string, email: string) {
const trimmedEmail = email.toLowerCase().trim();
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(trimmedEmail)) {
return { success: false, error: "Invalid email format" };
}
// Reuse encryption logic pattern
const hash = crypto.createHash('sha256').update(trimmedEmail).digest('hex');
const encryptionKey = process.env.ENCRYPTION_KEY || "";
if (!encryptionKey || encryptionKey.length !== 64) {
return { success: false, error: "Server configuration error" };
}
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(encryptionKey, 'hex'), iv);
let encrypted = cipher.update(trimmedEmail, 'utf8', 'hex');
encrypted += cipher.final('hex');
const emailEncrypted = iv.toString('hex') + ':' + encrypted;
try {
// Find internal video ID
const video = await db.query.youtubeVideos.findFirst({
where: eq(youtubeVideos.videoId, videoId)
});
if (!video) return { success: false, error: "Video not found" };
await db.insert(analysisNotifications).values({
videoId: video.id,
emailHash: hash,
emailEncrypted: emailEncrypted,
status: 'PENDING'
});
return { success: true };
} catch (err) {
console.error("[requestAnalysisNotificationAction] Error:", err);
return { success: false, error: "Failed to register notification" };
}
}
import crypto from "crypto";
import { db } from "@/lib/db";
import { youtubeVideos, analysisNotifications } from "@/lib/db/schema";
import { eq } from "drizzle-orm";