onedrive_sync/main.js

248 lines
7.9 KiB
JavaScript

const { app, BrowserWindow, ipcMain, dialog, session } = require('electron');
require('@electron/remote/main').initialize();
const path = require('path');
const fs = require('fs');
const https = require('https');
let store;
let mainWindow;
let fetch;
// Initialize store and fetch using dynamic import
(async () => {
const [Store, { default: nodeFetch }] = await Promise.all([
import('electron-store'),
import('node-fetch')
]);
store = new Store.default();
fetch = nodeFetch;
console.log('Store and fetch initialized');
})();
function createWindow() {
console.log('Creating main window...');
mainWindow = new BrowserWindow({
width: 1200,
height: 800,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
webviewTag: true,
enableRemoteModule: true
}
});
// Enable remote module for this window
require('@electron/remote/main').enable(mainWindow.webContents);
// Set up network request monitoring
console.log('Setting up network request monitoring...');
session.defaultSession.webRequest.onBeforeRequest(
{ urls: ['*://*.onedrive.com/*', '*://*.1drv.com/*', '*://*.microsoftpersonalcontent.com/*'] },
(details, callback) => {
console.log('Intercepted request:', details.url);
// Check if this is a video request (typically .mov for Live Photos)
if (details.url.toLowerCase().includes('.mov') || details.url.toLowerCase().includes('mp4')) {
console.log('✓ Detected video URL:', details.url);
if (store) {
const destFolder = store.get('destFolder', '');
if (destFolder) {
// Extract item ID from URL
const urlObj = new URL(details.url);
const pathParts = urlObj.pathname.split('/');
const itemIndex = pathParts.findIndex(part => part === 'items');
const itemId = itemIndex !== -1 ? pathParts[itemIndex + 1] : null;
// Create filename with item ID and extension
const extension = details.url.toLowerCase().includes('.mov') ? '.mov' : '.mp4';
const filename = itemId ? `${itemId}${extension}` : `video_${Date.now()}${extension}`;
console.log('Downloading video as:', filename);
console.log('To folder:', destFolder);
console.log("cookies:", session.defaultSession.cookies);
// Print all cookies
session.defaultSession.cookies.get({})
.then((cookies) => {
console.log("cookies:", cookies);
})
.catch((error) => {
console.error('Failed to load cookies:', error);
});
downloadVideo(details.url, path.join(destFolder, filename));
} else {
console.warn('⚠ No destination folder configured');
}
} else {
console.error('⚠ Store not initialized');
}
}
callback({ cancel: false });
}
);
mainWindow.loadFile(path.join(__dirname, 'renderer/index.html'));
mainWindow.setTitle('OneDrive Photos');
console.log('Main window created and loaded');
}
function downloadVideo(url, filepath) {
console.log('Starting video download:', url);
// Get cookies from all relevant domains
Promise.all([
session.defaultSession.cookies.get({domain: '.onedrive.com'}),
session.defaultSession.cookies.get({domain: '.1drv.com'}),
session.defaultSession.cookies.get({domain: '.microsoftpersonalcontent.com'})
])
.then((cookieArrays) => {
// Flatten and combine all cookies
const allCookies = [].concat(...cookieArrays);
console.log('All cookies found:', allCookies);
const cookieHeader = allCookies
.map(cookie => `${cookie.name}=${cookie.value}`)
.join('; ');
const options = {
headers: {
'Cookie': cookieHeader,
'Accept': '*/*',
'User-Agent': 'Mozilla/5.0',
'Authorization': `Bearer ${allCookies.find(c => c.name === 'AccessToken-OneDrive.ReadWrite')?.value || ''}`,
'Origin': 'https://photos.onedrive.com',
'Referer': 'https://photos.onedrive.com/'
}
};
console.log('Request headers:', options.headers);
// Rest of the download code...
const file = fs.createWriteStream(filepath);
https.get(url, options, (response) => {
console.log('Download started, status:', response.statusCode);
console.log('Response headers:', response.headers);
if (response.statusCode === 401 || response.statusCode === 403) {
console.error('Authentication failed:', response.statusCode);
mainWindow.webContents.send('video-save-error', 'Authentication failed');
return;
}
response.pipe(file);
file.on('finish', () => {
file.close();
console.log('✓ Video saved successfully:', filepath);
mainWindow.webContents.send('video-saved', {
filename: path.basename(filepath),
path: filepath
});
});
}).on('error', (err) => {
console.error('⚠ Download error:', err);
fs.unlink(filepath, () => {
console.log('Cleaned up failed download file');
});
mainWindow.webContents.send('video-save-error', err.message);
});
})
.catch((error) => {
console.error('Failed to load cookies for download:', error);
mainWindow.webContents.send('video-save-error', 'Failed to load authentication cookies');
});
}
app.whenReady().then(createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
// IPC Handlers with debug logs
ipcMain.on('toggle-config', () => {
console.log('Toggle config panel requested');
mainWindow.webContents.send('toggle-config');
});
ipcMain.on('set-config', (event, config) => {
console.log('Saving configuration:', config);
if (store) {
store.set('destFolder', config.destFolder);
store.set('onedriveSource', config.onedriveSource);
console.log('✓ Configuration saved successfully');
} else {
console.error('⚠ Store not initialized, cannot save config');
}
});
ipcMain.on('load-config', (event) => {
console.log('Loading configuration...');
if (store) {
const config = {
destFolder: store.get('destFolder', ''),
onedriveSource: store.get('onedriveSource', '')
};
console.log('Configuration loaded:', config);
event.reply('config-loaded', config);
} else {
console.error('⚠ Store not initialized, cannot load config');
}
});
ipcMain.on('select-folder', (event) => {
dialog.showOpenDialog({
properties: ['openDirectory']
}).then(result => {
if (!result.canceled) {
event.reply('folder-selected', result.filePaths[0]);
}
}).catch(err => {
console.log(err);
});
});
ipcMain.on('start-sync', async (event, { destFolder, onedriveSource, items }) => {
console.log('Starting sync with config:', { destFolder, onedriveSource });
console.log(`Processing ${items.length} items...`);
try {
// Filter for video files (Live Photos)
const videoItems = items.filter(item =>
item.name.toLowerCase().endsWith('.mov') ||
item.name.toLowerCase().endsWith('.mp4')
);
console.log(`Found ${videoItems.length} video items`);
// Process each video item
for (const item of videoItems) {
if (item['@microsoft.graph.downloadUrl']) {
const filename = `${item.id}${path.extname(item.name)}`;
const filepath = path.join(destFolder, filename);
console.log(`Downloading: ${item.name} as ${filename}`);
await downloadVideo(item['@microsoft.graph.downloadUrl'], filepath);
} else {
console.warn(`No download URL for item: ${item.name}`);
}
}
event.reply('sync-complete', {
totalItems: items.length,
videoItems: videoItems.length
});
} catch (error) {
console.error('Sync error:', error);
event.reply('sync-error', error.message);
}
});