// Google Photos API Test // // Usage: // node TEST/testGooglePhotosAPI.js // GOOGLE_ACCESS_TOKEN=ya29.xxx node TEST/testGooglePhotosAPI.js // // Getting a token from OAuth Playground (https://developers.google.com/oauthplayground): // 1. Click the gear icon → check "Use your own OAuth credentials" // 2. Enter your Client ID and Client Secret from Google Cloud Console // 3. In the left panel select ALL of these scopes: // https://www.googleapis.com/auth/photoslibrary // https://www.googleapis.com/auth/photoslibrary.appendonly // https://www.googleapis.com/auth/userinfo.email // https://www.googleapis.com/auth/userinfo.profile // 4. Click "Authorize APIs" and sign in with your test Google account // 5. Click "Exchange authorization code for tokens" // 6. Copy the Access token (starts with ya29.) and pass it here // // Note: if you only see 403 PERMISSION_DENIED, the token was issued without // the photoslibrary scope — go back and re-authorise with all scopes above. const API_BASE = 'https://photoslibrary.googleapis.com/v1'; const USERINFO_URL = 'https://www.googleapis.com/oauth2/v2/userinfo'; async function main() { const token = process.argv[2] || process.env.GOOGLE_ACCESS_TOKEN; if (!token) { console.error('\nNo access token provided.'); console.error('Usage: node TEST/testGooglePhotosAPI.js '); console.error('Or set: GOOGLE_ACCESS_TOKEN=ya29.xxx node TEST/testGooglePhotosAPI.js'); console.error('\nTo obtain a token go to https://developers.google.com/oauthplayground'); console.error('and authorise the Photos Library API v1 scope.\n'); process.exit(1); } const headers = { Authorization: `Bearer ${token}` }; console.log('\n--- Google Photos API Test ---\n'); // Test 1 — User info console.log('[1] Fetching user info...'); try { const res = await fetch(USERINFO_URL, { headers }); if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`); const user = await res.json(); console.log(` Authenticated as: ${user.email} (${user.name})\n`); } catch (err) { console.log(` Failed: ${err.message}\n`); } // Test 2 — List media items console.log('[2] Listing media items (first 10)...'); try { const res = await fetch(`${API_BASE}/mediaItems?pageSize=10`, { headers }); if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`); const data = await res.json(); const items = data.mediaItems || []; console.log(` Found ${items.length} items`); items.slice(0, 5).forEach((item, i) => { console.log(` ${i + 1}. ${item.filename} (${item.mimeType})`); }); if (items.length > 5) console.log(` ... and ${items.length - 5} more`); if (data.nextPageToken) console.log(' More pages available'); console.log(); } catch (err) { console.log(` Failed: ${err.message}\n`); } // Test 3 — List albums console.log('[3] Listing albums...'); try { const res = await fetch(`${API_BASE}/albums?pageSize=10`, { headers }); if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`); const data = await res.json(); const albums = data.albums || []; console.log(` Found ${albums.length} albums`); albums.slice(0, 5).forEach((album, i) => { console.log(` ${i + 1}. "${album.title}" - ${album.mediaItemsCount || 0} items`); }); console.log(); } catch (err) { console.log(` Failed: ${err.message}\n`); } console.log('--- Tests complete ---\n'); } main().catch((err) => { console.error('Unhandled error:', err); process.exit(1); });