Last active
February 15, 2025 14:27
-
-
Save camilomontoyau/0458a683b58916fb2e9da5afaf7e7101 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const { google } = require('googleapis'); | |
| const { authenticate } = require('@google-cloud/local-auth'); | |
| const fs = require('fs').promises; | |
| const oldFs = require('fs'); | |
| const path = require('path'); | |
| const process = require('process'); | |
| const SCOPES = ['https://www.googleapis.com/auth/photoslibrary.readonly']; | |
| const TOKEN_PATH = path.join(process.cwd(), 'token.json'); | |
| const CREDENTIALS_PATH = path.join(process.cwd(), 'credentials.json'); | |
| async function loadSavedCredentialsIfExist() { | |
| try { | |
| const content = await fs.readFile(TOKEN_PATH); | |
| const credentials = JSON.parse(content); | |
| return google.auth.fromJSON(credentials); | |
| } catch { | |
| return null; | |
| } | |
| } | |
| async function saveCredentials(client) { | |
| const content = await fs.readFile(CREDENTIALS_PATH); | |
| const keys = JSON.parse(content); | |
| const key = keys.installed || keys.web; | |
| const payload = JSON.stringify({ | |
| type: 'authorized_user', | |
| client_id: key.client_id, | |
| client_secret: key.client_secret, | |
| refresh_token: client.credentials.refresh_token, | |
| }); | |
| await fs.writeFile(TOKEN_PATH, payload); | |
| } | |
| async function authorize() { | |
| let client = await loadSavedCredentialsIfExist(); | |
| if (client) return client; | |
| client = await authenticate({ | |
| scopes: SCOPES, | |
| keyfilePath: CREDENTIALS_PATH, | |
| }); | |
| if (client.credentials) { | |
| await saveCredentials(client); | |
| } | |
| return client; | |
| } | |
| async function listAllMediaItems(auth) { | |
| let allItems = []; | |
| let pageToken = null; | |
| do { | |
| const url = pageToken | |
| ? `https://photoslibrary.googleapis.com/v1/mediaItems?pageSize=100&pageToken=${pageToken}` | |
| : 'https://photoslibrary.googleapis.com/v1/mediaItems?pageSize=100'; | |
| console.log(`Fetching media items from: ${url}`); | |
| try { | |
| const res = await auth.request({ url }); | |
| const items = res.data.mediaItems || []; | |
| allItems = allItems.concat(items); | |
| pageToken = res.data.nextPageToken; | |
| } catch (err) { | |
| console.log('Error fetching media items:', err); | |
| // throw err; | |
| } | |
| // break; | |
| } while (pageToken); | |
| console.log(`Total media items: ${allItems.length}`); | |
| return allItems; | |
| } | |
| async function downloadPhotos() { | |
| try { | |
| const auth = await authorize(); | |
| const mediaItems = await listAllMediaItems(auth); | |
| console.log('mediaItems: ================='); | |
| console.log(JSON.stringify(mediaItems, null, 2)); | |
| console.log('================='); | |
| if (!mediaItems.length) { | |
| console.log('No photos to download.'); | |
| return; | |
| } | |
| const downloadDir = path.join(process.cwd(), 'downloads'); | |
| try { | |
| await fs.mkdir(downloadDir); | |
| } catch {} | |
| for (const item of mediaItems) { | |
| const url = `${item.baseUrl}=d`; | |
| const filePath = path.join(downloadDir, item.filename || `${item.id}.jpg`); | |
| console.log(`Downloading ${item.filename || item.id} from ${url}`); | |
| // check if file already exists | |
| try { | |
| if(oldFs.existsSync(filePath)) { | |
| console.log(`File already exists: ${item.filename || item.id}`); | |
| continue; | |
| } | |
| } catch (error) { | |
| console.log(`Failed to access ${item.filename || item.id}:`, error); | |
| continue; | |
| } | |
| try { | |
| const response = await fetch(url); | |
| if (!response.ok) { | |
| throw new Error(`Failed to download ${item.filename || item.id}: ${response.statusText}`); | |
| } | |
| const buffer = await response.arrayBuffer(); | |
| await fs.writeFile(filePath, Buffer.from(buffer)); | |
| console.log(`Downloaded ${item.filename || item.id}`); | |
| } catch (error) { | |
| console.log(`Failed to download ${item.filename || item.id}:`, error); | |
| } | |
| } | |
| console.log('Download complete.!!!!!!!!!'); | |
| } catch (error) { | |
| console.log('Error downloading photos:', error); | |
| } | |
| } | |
| downloadPhotos().catch(console.log); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "name": "download-photos-from-google", | |
| "version": "1.0.0", | |
| "description": "", | |
| "main": "download.js", | |
| "scripts": { | |
| "test": "echo \"Error: no test specified\" && exit 1" | |
| }, | |
| "keywords": [], | |
| "author": "", | |
| "license": "ISC", | |
| "dependencies": { | |
| "@google-cloud/local-auth": "^3.0.1", | |
| "google-auth-library": "^9.15.1", | |
| "googleapis": "^144.0.0", | |
| "node-fetch": "^3.3.2", | |
| "readline": "^1.3.0" | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment