/** * Import ChatGPT conversations using OpenAI's Conversations API */ import { NextResponse } from 'next/server'; import { getAdminAuth, getAdminDb } from '@/lib/firebase/admin'; const OPENAI_API_URL = 'https://api.openai.com/v1/conversations'; export async function POST(request: Request) { try { // Authenticate user const authHeader = request.headers.get('Authorization'); if (!authHeader?.startsWith('Bearer ')) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const idToken = authHeader.split('Bearer ')[1]; const adminAuth = getAdminAuth(); const adminDb = getAdminDb(); let userId: string; try { const decodedToken = await adminAuth.verifyIdToken(idToken); userId = decodedToken.uid; } catch (error) { return NextResponse.json({ error: 'Invalid token' }, { status: 401 }); } const { conversationId, openaiApiKey, projectId } = await request.json(); if (!conversationId) { return NextResponse.json({ error: 'Conversation ID is required' }, { status: 400 }); } if (!openaiApiKey) { return NextResponse.json({ error: 'OpenAI API key is required' }, { status: 400 }); } // Fetch conversation from OpenAI console.log(`[ChatGPT Import] Fetching conversation: ${conversationId}`); const openaiResponse = await fetch(`${OPENAI_API_URL}/${conversationId}`, { method: 'GET', headers: { 'Authorization': `Bearer ${openaiApiKey}`, 'Content-Type': 'application/json', }, }); if (!openaiResponse.ok) { const errorText = await openaiResponse.text(); console.error('[ChatGPT Import] OpenAI API error:', openaiResponse.status, errorText); return NextResponse.json( { error: 'Failed to fetch conversation from OpenAI', details: errorText, status: openaiResponse.status, }, { status: openaiResponse.status } ); } const conversationData = await openaiResponse.json(); console.log('[ChatGPT Import] Conversation fetched successfully'); // Extract relevant information const messages = conversationData.messages || []; const title = conversationData.title || 'Untitled Conversation'; const createdAt = conversationData.created_at || new Date().toISOString(); // Store in Firestore const chatGPTImportRef = adminDb.collection('chatgptImports').doc(); await chatGPTImportRef.set({ userId, projectId: projectId || null, conversationId, title, createdAt, importedAt: new Date().toISOString(), messageCount: messages.length, messages: messages.map((msg: any) => ({ role: msg.role || msg.author?.role || 'unknown', content: msg.content?.parts?.join('\n') || msg.content || '', timestamp: msg.create_time || msg.timestamp || null, })), rawData: conversationData, // Store full response for future reference }); // If projectId provided, update project with ChatGPT reference if (projectId) { const projectRef = adminDb.collection('projects').doc(projectId); await projectRef.update({ chatgptConversationId: conversationId, chatgptTitle: title, chatgptImportedAt: new Date().toISOString(), }); console.log(`[ChatGPT Import] Updated project ${projectId} with conversation reference`); } return NextResponse.json({ success: true, importId: chatGPTImportRef.id, conversationId, title, messageCount: messages.length, messages: messages.slice(0, 5).map((msg: any) => ({ role: msg.role || msg.author?.role || 'unknown', preview: (msg.content?.parts?.join('\n') || msg.content || '').substring(0, 200) + '...', })), }); } catch (error) { console.error('[ChatGPT Import] Error:', error); return NextResponse.json( { error: 'Failed to import ChatGPT conversation', details: error instanceof Error ? error.message : String(error), }, { status: 500 } ); } } // GET endpoint to list imported conversations export async function GET(request: Request) { try { const authHeader = request.headers.get('Authorization'); if (!authHeader?.startsWith('Bearer ')) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const idToken = authHeader.split('Bearer ')[1]; const adminAuth = getAdminAuth(); const adminDb = getAdminDb(); let userId: string; try { const decodedToken = await adminAuth.verifyIdToken(idToken); userId = decodedToken.uid; } catch (error) { return NextResponse.json({ error: 'Invalid token' }, { status: 401 }); } // Get projectId from query params if provided const url = new URL(request.url); const projectId = url.searchParams.get('projectId'); let query = adminDb .collection('chatgptImports') .where('userId', '==', userId); if (projectId) { query = query.where('projectId', '==', projectId) as any; } const snapshot = await query.orderBy('importedAt', 'desc').limit(50).get(); const imports = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data(), // Don't send full rawData in list view rawData: undefined, })); return NextResponse.json({ imports }); } catch (error) { console.error('[ChatGPT Import] List error:', error); return NextResponse.json( { error: 'Failed to list imports', details: error instanceof Error ? error.message : String(error), }, { status: 500 } ); } }