248 lines
7.9 KiB
JavaScript
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);
|
|
}
|
|
});
|