109 lines
3.3 KiB
TypeScript
109 lines
3.3 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { spawn } from "child_process";
|
|
import fs from "fs";
|
|
import path from "path";
|
|
|
|
const STORAGE_FILE = "/root/.openclaw/workspace/SiteMente/data/transcripts.json";
|
|
|
|
function getTranscripts() {
|
|
if (fs.existsSync(STORAGE_FILE)) {
|
|
return JSON.parse(fs.readFileSync(STORAGE_FILE, "utf-8"));
|
|
}
|
|
return [];
|
|
}
|
|
|
|
function saveTranscript(data) {
|
|
const transcripts = getTranscripts();
|
|
// Check if already exists
|
|
const existing = transcripts.findIndex(t => t.videoId === data.videoId);
|
|
if (existing >= 0) {
|
|
transcripts[existing] = data;
|
|
} else {
|
|
transcripts.unshift(data);
|
|
}
|
|
fs.writeFileSync(STORAGE_FILE, JSON.stringify(transcripts, null, 2));
|
|
return transcripts;
|
|
}
|
|
|
|
export async function GET(request: NextRequest) {
|
|
const { searchParams } = new URL(request.url);
|
|
const videoId = searchParams.get("videoId");
|
|
|
|
const transcripts = getTranscripts();
|
|
|
|
if (videoId) {
|
|
const found = transcripts.find(t => t.videoId === videoId);
|
|
return NextResponse.json(found || { error: "Not found" });
|
|
}
|
|
|
|
return NextResponse.json(transcripts);
|
|
}
|
|
|
|
export async function POST(request: NextRequest) {
|
|
try {
|
|
const body = await request.json();
|
|
const { action, videoUrl, videoId, transcript, title, categories } = body;
|
|
|
|
// Extract video ID if not provided
|
|
let vid = videoId;
|
|
if (!vid && videoUrl) {
|
|
const match = videoUrl.match(/(?:v=|\/)([0-9A-Za-z_-]{11})/);
|
|
vid = match ? match[1] : videoUrl;
|
|
}
|
|
|
|
if (action === "fetch") {
|
|
// Run Python script to get transcript
|
|
return new Promise((resolve) => {
|
|
const scriptPath = "/root/.openclaw/workspace/scripts/youtube_transcript.py";
|
|
const outputFile = `/tmp/transcript_${vid}.txt`;
|
|
|
|
const proc = spawn("python3", [scriptPath, vid], {
|
|
cwd: "/root/.openclaw/workspace/scripts"
|
|
});
|
|
|
|
let output = "";
|
|
let error = "";
|
|
|
|
proc.stdout.on("data", (data) => { output += data.toString(); });
|
|
proc.stderr.on("data", (data) => { error += data.toString(); });
|
|
|
|
proc.on("close", (code) => {
|
|
if (fs.existsSync(outputFile)) {
|
|
const transcriptText = fs.readFileSync(outputFile, "utf-8");
|
|
resolve(NextResponse.json({
|
|
success: true,
|
|
videoId: vid,
|
|
transcript: transcriptText
|
|
}));
|
|
} else {
|
|
resolve(NextResponse.json({
|
|
success: false,
|
|
error: error || "Could not fetch transcript"
|
|
}, { status: 500 }));
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
if (action === "save") {
|
|
// Save transcript with metadata
|
|
const data = {
|
|
videoId: vid,
|
|
videoUrl: videoUrl || `https://www.youtube.com/watch?v=${vid}`,
|
|
title: title || `Video ${vid}`,
|
|
transcript: transcript || "",
|
|
categories: categories || [],
|
|
savedAt: new Date().toISOString()
|
|
};
|
|
|
|
const updated = saveTranscript(data);
|
|
return NextResponse.json({ success: true, transcripts: updated });
|
|
}
|
|
|
|
return NextResponse.json({ error: "Invalid action" }, { status: 400 });
|
|
|
|
} catch (error) {
|
|
return NextResponse.json({ error: "Internal server error" }, { status: 500 });
|
|
}
|
|
}
|