const express = require('express'); const cors = require('cors'); const multer = require('multer'); const fs = require('fs'); const path = require('path'); const app = express(); app.use(cors({ origin: ['http://localhost:3000'] })); app.use(express.json()); const upload = multer({ storage: multer.memoryStorage(), limits: { fileSize: 10 * 1024 * 1024 } }); const uploads = {}; // Adobe PDF Services let adobeCredentials = null; try { const PDFServicesSdk = require('@adobe/pdfservices-node-sdk'); const creds = JSON.parse(fs.readFileSync('./pdfservices-api-credentials.json', 'utf8')); adobeCredentials = new PDFServicesSdk.ServicePrincipalCredentials({ clientId: creds.client_credentials.client_id, clientSecret: creds.client_credentials.client_secret }); console.log('โ Adobe OCR ENABLED'); } catch (e) { console.log('โ ๏ธ Adobe OCR disabled, using basic extraction'); } // PDF extraction with text cleaning async function extractTextBasic(pdfBuffer) { const pdfParse = require('pdf-parse'); const data = await pdfParse(pdfBuffer); // Clean the text let cleanText = data.text .replace(/74222 - Aug 20, 2025 9:42 AM -/g, '') .replace(/B568CR-/g, '') .replace(/Sides by Breakdown Services - Actors Access/g, '') .replace(/\d{1,2}\.\s*/g, '') .replace(/\s+/g, ' ') .trim(); console.log('๐งน Cleaned text from', data.text.length, 'to', cleanText.length, 'characters'); return { text: cleanText, method: 'basic', confidence: 'medium', characterNames: [], stageDirections: [] }; } // PDF Upload app.post('/api/upload', upload.single('file'), async (req, res) => { try { if (!req.file || req.file.mimetype !== 'application/pdf') { return res.status(400).json({ error: 'Please upload a PDF file' }); } console.log(`๐ Processing: ${req.file.originalname}`); const result = await extractTextBasic(req.file.buffer); if (!result.text || result.text.trim().length < 10) { return res.status(400).json({ error: 'Could not extract readable text from PDF' }); } const uploadId = Date.now().toString(); uploads[uploadId] = { filename: req.file.originalname, sceneText: result.text.trim(), extractionMethod: result.method, uploadTime: new Date(), wordCount: result.text.trim().split(/\s+/).length }; console.log(`โ Extracted ${result.text.length} characters using ${result.method}`); res.json({ uploadId, filename: req.file.originalname, textLength: result.text.length, wordCount: uploads[uploadId].wordCount, extractionMethod: result.method, extractionConfidence: result.confidence, characterNames: [], preview: result.text.substring(0, 300) + '...', success: true }); } catch (error) { console.error('โ Upload error:', error); res.status(500).json({ error: 'Failed to process PDF' }); } }); // DYNAMIC PROMPT GENERATION BASED ON GENRE const generateUserPrompt = (data) => { // Detect script genre/tone for appropriate guidance const scriptText = data.sceneText.toLowerCase(); const isComedy = scriptText.includes('laugh') || scriptText.includes('funny') || data.productionType.toLowerCase().includes('comedy') || data.productionType.toLowerCase().includes('sitcom'); const isDrama = data.productionType.toLowerCase().includes('drama') || scriptText.includes('cry') || scriptText.includes('serious'); return `You are an expert acting coach analyzing an audition script. Create a professional preparation guide that helps the actor book this job. CHARACTER: ${data.characterName} PRODUCTION: ${data.productionTitle} (${data.productionType}) GENRE: ${isComedy ? 'Comedy' : isDrama ? 'Drama' : 'Mixed Genre'} SCRIPT TO ANALYZE: ${data.sceneText} Create a comprehensive acting guide with these sections (use proper markdown formatting): ## CHARACTER ESSENCE Write 3-4 sentences capturing this character's core psychology and what makes them unique. Go beyond demographics to their emotional core and worldview. ## SCRIPT BREAKDOWN Analyze 3-4 specific moments from the provided script. For each moment, include: - The actual line or action from the script - What's really happening beneath the surface - The character's emotional state and objective ## UTA HAGEN'S 9 QUESTIONS Answer each question specifically for this character and script: **Who am I?** (Character background in first person) **Where am I?** (Location analysis and character's relationship to space) **What time is it?** (Time context and energy impact) **What surrounds me?** (Environment and its emotional effect) **What are the relationships?** (Dynamic with each character mentioned) **What are the circumstances?** (Events leading to this scene) **What do I want?** (Scene objectives moment by moment) **What's in my way?** (Obstacles and conflicts) **How do I get what I want?** (Tactics and behaviors) ## SUBTEXT ANALYSIS For 3-4 actual lines from the script, reveal what the character is REALLY saying: - "Line from script" = What they really mean - Include the psychological motivation behind each line ## PHYSICALITY & VOICE Based on the script, describe: - How this character moves and uses their body - Vocal qualities that serve the character - Physical actions that reveal personality ${isComedy ? `## COMEDY STRATEGY - Where are the laugh moments in this script? - How to land jokes without "trying to be funny" - Timing and rhythm specific to this scene` : isDrama ? `## DRAMATIC TECHNIQUE - Emotional peaks and valleys in the script - How to build genuine emotion - Vulnerability and truth moments` : `## GENRE APPROACH - How to balance different tonal elements - Moments that require different acting approaches`} ## BOLD CHOICES Provide 3 specific, unexpected choices the actor could make that would: - Serve the story authentically - Make them memorable to casting - Differentiate them from obvious interpretations ## MOMENT BEFORE & BUTTON - **Moment Before**: What happened 30 seconds before this scene starts? - **The Button**: 2-3 options for how to end the scene memorably ## ACTION PLAN Create 8 specific preparation tasks for this actor and this script. CRITICAL REQUIREMENTS: - Reference actual dialogue from the script throughout your analysis - Make every piece of advice specific to THIS character and script - Write with professional coaching expertise - Provide actionable, not theoretical advice - Focus on choices that help the actor book the job Generate this as clean, well-formatted content (no HTML tags in your response - just clear markdown formatting).`; }; // ENHANCED GUIDE GENERATION FUNCTION async function generateActingGuide(data) { const fetch = require('node-fetch'); const systemPrompt = `You are a professional acting coach with 20+ years of industry experience. You've coached actors who've booked major TV shows, films, and theater productions. Your expertise includes: - Uta Hagen's 9 Questions methodology - Script analysis and subtext work - Genre-specific techniques (comedy timing, dramatic truth, etc.) - Self-tape and audition strategy - Character development techniques You provide practical, actionable coaching that helps actors book jobs. Your advice is specific, never generic, and always serves the story while helping the actor stand out.`; const userPrompt = generateUserPrompt(data); try { console.log(`๐ญ Generating professional guide for ${data.characterName}...`); const response = await fetch('https://api.anthropic.com/v1/messages', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': "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", 'anthropic-version': '2023-06-01' }, body: JSON.stringify({ model: "claude-3-5-sonnet-20241022", max_tokens: 4000, system: systemPrompt, messages: [{ role: "user", content: userPrompt }] }) }); if (!response.ok) { throw new Error(`API Error: ${response.status}`); } const result = await response.json(); if (result.content && result.content[0] && result.content[0].text) { console.log(`โ Professional guide generated successfully`); return formatGuideAsHTML(result.content[0].text, data); } else { throw new Error('Invalid response format from API'); } } catch (error) { console.error('โ Guide generation failed:', error.message); throw error; } } // Fallback template function generateFallbackGuide(data) { return `
${data.sceneText}
All Claude models failed to generate the professional guide. Check your API key and internet connection.
This fallback template shows your script was processed successfully.