Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions app/api/users/create/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,26 @@ import { getAdminDB } from '@/lib/firebase-admin';
import { NextResponse } from 'next/server';
import { encryptToken } from '@/lib/encryption';


export async function POST(request: Request) {
try {
console.log('🔔 Starting user creation/update process');
console.log('[Create User] Starting user creation/update process');
const adminDb = getAdminDB();
const { uid, email, displayName, accessToken, photoURL } = await request.json();
console.log('📝 User data received:', { uid, email, displayName });
console.log('[Create User] User data received:', { uid, email, displayName, hasToken: !!accessToken });

// Encrypt the access token before storing
console.log('[Create User] Encrypting access token...');
const encryptedToken = await encryptToken(accessToken);
console.log('[Create User] Token encrypted, length:', encryptedToken?.length);

// First check if users collection exists and if this user exists
const usersRef = adminDb.collection('users');
const userDoc = await usersRef.doc(uid).get();
const now = new Date();

if (!userDoc.exists) {
console.log('👤 Creating new user document');
console.log('[Create User] Creating new user document');
// User doesn't exist, create new user document
await usersRef.doc(uid).set({
uid,
Expand All @@ -30,11 +33,11 @@ export async function POST(request: Request) {
lastLogin: now,
hasWatchHistory: false
});
console.log(' New user created successfully');
console.log('[Create User] New user created successfully');
return NextResponse.json({ success: true, isNewUser: true });
}

console.log('🔄 Updating existing user');
console.log('[Create User] Updating existing user');
// Update existing user's last login
await usersRef.doc(uid).update({
lastLogin: now,
Expand All @@ -43,15 +46,15 @@ export async function POST(request: Request) {
displayName,
photoURL,
});
console.log(' User updated successfully');
console.log('[Create User] User updated successfully');

return NextResponse.json({
success: true,
isNewUser: false,
hasWatchHistory: userDoc.data()?.hasWatchHistory || false
});
} catch (error) {
console.error('❌ Error in user creation/update:', error);
console.error('[Create User] ERROR:', error);
return NextResponse.json({
error: 'Failed to create/update user',
details: error instanceof Error ? error.message : 'Unknown error'
Expand Down
73 changes: 63 additions & 10 deletions app/api/users/get-history/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,61 +6,114 @@ import { fetchAndExtractZip } from '@/lib/google-drive-backend';

export async function GET(request: Request) {
try {
console.log('🔔 Starting watch history fetch process');
console.log('\n========== GET /api/users/get-history ==========');
console.log('[Step 1] Starting watch history fetch process');

// Initialize Firebase Admin first
console.log('[Step 2] Initializing Firebase Admin...');
const adminDb = getAdminDB();
console.log('[Step 2] Firebase Admin initialized successfully');

// Get the authorization header
console.log('[Step 3] Checking authorization header...');
const authHeader = request.headers.get('Authorization');
if (!authHeader?.startsWith('Bearer ')) {
console.log(' No authorization header found');
console.log('[Step 3] FAILED: No authorization header found');
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
console.log('[Step 3] Authorization header present');

const idToken = authHeader.split('Bearer ')[1];
console.log('[Step 4] Verifying ID token (length:', idToken?.length, ')');

// Verify the ID token
const auth = getAuth();
const decodedToken = await auth.verifyIdToken(idToken);
const uid = decodedToken.uid;

console.log('📝 Fetching watch history for user:', uid);
console.log('[Step 4] Token verified, uid:', uid);

// Get the user's document from Firestore
console.log('[Step 5] Fetching user document from Firestore...');
const userDoc = await adminDb.collection('users').doc(uid).get();
console.log('[Step 5] User document fetched, exists:', userDoc.exists);

if (!userDoc.exists) {
console.log(' User document not found');
console.log('[Step 5] FAILED: User document not found');
return NextResponse.json({ error: 'User not found' }, { status: 404 });
}

const userData = userDoc.data();
const encryptedToken = userData?.accessToken;
console.log('[Step 6] Checking encrypted token, present:', !!encryptedToken, ', length:', encryptedToken?.length);

if (!encryptedToken) {
console.log(' No access token found for user');
console.log('[Step 6] FAILED: No access token found for user');
return NextResponse.json({ error: 'No access token found' }, { status: 404 });
}
console.log('[Step 6] Encrypted token found');

// Decrypt the token
console.log('[Step 7] Decrypting access token...');
const accessToken = await decryptToken(encryptedToken);
console.log('[Step 7] Token decrypted successfully, length:', accessToken?.length);

// Use the token to fetch watch history data
console.log('[Step 8] Fetching watch history from Google Drive...');
const watchHistoryData = await fetchAndExtractZip(accessToken);
const dataInfo = Array.isArray(watchHistoryData)
? `array with ${watchHistoryData.length} entries`
: `object with keys: ${Object.keys(watchHistoryData || {}).slice(0, 5).join(', ')}`;
console.log('[Step 8] Watch history fetched:', dataInfo);

// Update the user's last data update timestamp
console.log('[Step 9] Updating lastDataUpdate timestamp...');
await adminDb.collection('users').doc(uid).update({
lastDataUpdate: new Date(),
});
console.log('[Step 9] Timestamp updated');

console.log('✅ Successfully retrieved and processed watch history data');
console.log('[SUCCESS] Watch history fetch complete');
console.log('=================================================\n');
return NextResponse.json({ data: watchHistoryData });
} catch (error) {
console.error('❌ Error fetching watch history:', error);
console.error('\n[ERROR] /api/users/get-history failed');
console.error('Error type:', error instanceof Error ? error.constructor.name : typeof error);
console.error('Error message:', error instanceof Error ? error.message : String(error));
console.error('Error stack:', error instanceof Error ? error.stack : 'No stack trace');
console.error('=================================================\n');

// Return more specific error info for debugging
const errorMessage = error instanceof Error ? error.message : 'Unknown error';

// Categorize errors for better client-side handling
if (errorMessage.includes('No Takeout zip files found')) {
return NextResponse.json({
error: 'NO_TAKEOUT_FOLDER',
message: 'No Google Takeout export found in your Drive. Please create one first.',
details: errorMessage
}, { status: 404 });
}

if (errorMessage.includes('decrypt') || errorMessage.includes('Unsupported state')) {
return NextResponse.json({
error: 'TOKEN_ERROR',
message: 'Session expired. Please log out and log in again.',
details: errorMessage
}, { status: 401 });
}

if (errorMessage.includes('Watch history file not found')) {
return NextResponse.json({
error: 'INVALID_TAKEOUT',
message: 'Your Takeout export does not contain YouTube watch history. Please export with history included.',
details: errorMessage
}, { status: 404 });
}

return NextResponse.json({
error: 'Failed to fetch watch history',
details: error instanceof Error ? error.message : 'Unknown error'
error: 'FETCH_FAILED',
message: 'Failed to fetch watch history',
details: errorMessage
}, { status: 500 });
}
}
Loading
Loading