import { app } from 'electron';
import AdmZip from 'adm-zip';
const requestSavePath = path.join(app.getAppPath(), 'data');
class Instagram extends Provider {
async parseDataRequest(extractionPath: string): Promise<ProviderFile[]> {
return withSecureWindow<ProviderFile[]>(windowParams, async (window) => {
await new Promise((resolve) => {
window.webContents.once('did-finish-load', resolve)
window.loadURL('https://www.instagram.com/download/request/');
await new Promise((resolve) => {
// Now we defer to the user to enter their credentials
window.webContents.once('did-navigate', resolve);
window.webContents.executeJavaScript(`
Array.from(document.querySelectorAll('button'))
.find(el => el.textContent === 'Log In Again')
// We can now show the window for the login screen
// Then we'll await the navigation back to the data download page from
await new Promise((resolve) => {
window.webContents.once('will-navigate', resolve);
// We can now close the window
// Now that we're successfully authenticated on the data download page,
// the only thing we have to do is download the data.
const filePath = path.join(requestSavePath, 'instagram.zip');
await new Promise((resolve) => {
// Create a handler for any file saving actions
window.webContents.session.once('will-download', (event, item) => {
// Save the item to the data folder temporarily
item.setSavePath(filePath);
item.once('done', resolve);
// And then trigger the button click
window.webContents.executeJavaScript(`
Array.from(document.querySelectorAll('button'))
.find(el => el.textContent === 'Download Data')
// We have the ZIP, all that's left to do is unpack it and pipe it to
const zip = new AdmZip(filePath);
await new Promise((resolve) =>
zip.extractAllToAsync(extractionPath, true, resolve)
// Translate this into a form that is readable for the ParserManager
const files = zip.getEntries().map((entry): ProviderFile => {
filepath: entry.entryName,
// And dont forget to remove the zip file after it's been processed
await fs.promises.unlink(filePath);