This code snippet automates the creation and download of a Google Takeout archive for a specified product, handling navigation, login, size selection, archive creation, and download completion.
npm run import -- "download google takeout"
var importer = require('../Core');
function listTakeouts() {
return client
.url('https://takeout.google.com/settings/takeout')
.loginGoogle()
.pause(1000)
.url('https://takeout.google.com/settings/takeout')
.getAllXPath([
'//*[@data-id]',
{
id: './@data-id',
label: './/td[3]//text()'
}
])
};
function takeoutProducts(product) {
return client
.url('https://takeout.google.com/settings/takeout/custom/' + product.id)
.pause(500)
.click('//*[contains(@role, "button")][contains(., "Next")]')
.pause(500)
.click('//*[contains(., "Archive size")]/parent::*/*[contains(@role, "listbox")]') // [contains(@aria-selected, "true")]
.pause(500)
// TODO: shorten this in to a utility command
// doesn't work because of some weird css BS
// .click('//*[contains(@role, "option")][contains(., "50")]')
.click(
'//*[contains(., "Archive size")]/parent::*//*[contains(@role,"option")][contains(.,"50")]')
.pause(500)
.click('//*[contains(@role, "button")][contains(., "Create archive")]')
.waitUntil(
() => client.isExisting('//tr[1]//*[contains(@href, "takeout/download")]'),
120000,
'')
.isVisible('iframe[src*="settings"]')
.then(is => is ? client.execute(() => {
document.querySelector('iframe[src*="settings"]').remove();
}) : [])
.click('//tr[1]/td[last()]//*[contains(@href, "takeout/download")]')
.pause(1000)
.isVisible('#passwordNext')
.then(is => is ? client
.loginGoogle()
.then(is => is ? client.execute(() => {
const question = document.querySelector('iframe[src*="settings"]');
if(question) {
question.remove();
}
}) : [])
: [])
// wait for download
.pause(10000)
.catch(e => console.log(e))
}
function downloadGoogleTakeout(products) {
var regex = new RegExp(products, 'ig');
return listTakeouts()
.then(ids => {
return ids
.map(k => ({
id: k.id + '',
label: k.label + ''
}))
.filter(k => k.id != '_gd' && (products.indexOf('all') > -1
|| k.id.match(regex) != null || k.label.match(regex) != null))
})
.then(selectedProducts => {
console.log(selectedProducts);
return importer.runAllPromises(selectedProducts
.map(p => (resolve) => {
return takeoutProducts(p)
.then(r => resolve(r))
.catch(e => resolve(e))
}))
})
.catch(e => console.log(e))
};
if (typeof client.downloadGoogleTakeout == 'undefined') {
client.addCommand('downloadGoogleTakeout', downloadGoogleTakeout);
}
module.exports = downloadGoogleTakeout;
const { CommandBuilder } = require('../Core');
class GoogleTakeout {
/**
* Lists all available takeout products.
* @returns {Array} A list of objects containing the product ID and label.
*/
static listTakeouts() {
return this.client
.url('https://takeout.google.com/settings/takeout')
.loginGoogle()
.pause(1000)
.url('https://takeout.google.com/settings/takeout')
.getAllXPath([
'//*[@data-id]',
{
id: './@data-id',
label: './/td[3]//text()'
}
]);
}
/**
* Downloads a Google Takeout product.
* @param {Object} product - The product to download.
* @param {string} product.id - The ID of the product.
* @returns {Promise} A promise resolving to the download result.
*/
static takeoutProducts(product) {
return this.client
.url(`https://takeout.google.com/settings/takeout/custom/${product.id}`)
.pause(500)
.click('//*[contains(@role, "button")][contains(., "Next")]')
.pause(500)
.selectListbox('//*[contains(., "Archive size")]/parent::*/*[contains(@role, "listbox")]', '50')
.pause(500)
.click('//*[contains(@role, "button")][contains(., "Create archive")]')
.waitUntil(
() => this.client.isExisting('//tr[1]//*[contains(@href, "takeout/download")]'),
120000,
''
)
.then(is => is? this.client.execute(() => {
document.querySelector('iframe[src*="settings"]').remove();
}) : [])
.click('//tr[1]/td[last()]//*[contains(@href, "takeout/download")]')
.pause(1000)
.isVisible('#passwordNext')
.then(is => is? this.client
.loginGoogle()
.then(is => is? this.client.execute(() => {
const question = document.querySelector('iframe[src*="settings"]');
if (question) {
question.remove();
}
}) : [])
: [])
// wait for download
.pause(10000)
.catch(e => console.log(e));
}
/**
* Downloads the specified Google Takeout products.
* @param {string} products - The products to download (e.g. "email" or "all").
* @returns {Promise} A promise resolving to the download results.
*/
static downloadGoogleTakeout(products) {
const regex = new RegExp(products, 'ig');
return this.listTakeouts()
.then(ids => {
return ids
.map(k => ({
id: k.id + '',
label: k.label + ''
}))
.filter(k => k.id!== '_gd' && (products.includes('all') ||
k.id.match(regex)!== null || k.label.match(regex)!== null));
})
.then(selectedProducts => {
console.log(selectedProducts);
return this.client.runAllPromises(selectedProducts
.map(p => (resolve) => {
return this.takeoutProducts(p).then(r => resolve(r)).catch(e => resolve(e));
}));
})
.catch(e => console.log(e));
}
}
class CommandBuilder {
constructor() {
this.commands = {};
}
addCommand(name, method) {
this.commands[name] = method;
}
getCommand(name) {
return this.commands[name];
}
}
const builder = new CommandBuilder();
if (typeof builder.getCommand('downloadGoogleTakeout') === 'undefined') {
builder.addCommand('downloadGoogleTakeout', GoogleTakeout.downloadGoogleTakeout);
}
module.exports = builder;
This code snippet automates the process of creating and downloading a Google Takeout archive for a specific product.
Here's a breakdown:
1. listTakeouts
Function:
loginGoogle
(presumably a custom function).2. takeoutProducts
Function:
Overall:
This code snippet automates the process of creating and downloading a Google Takeout archive for a specific product. It handles navigation, login, selection of archive size, creation of the archive, and download.